Bir Linux sisteminin büyük endian veya küçük endian olup olmadığını nasıl anlarım?


91

Bazı işlemcilerin Büyük Endian ve diğerlerinin Küçük Endian olduğunu biliyorum. Ancak bir sistemin Büyük Endian mı yoksa Küçük Endian mı olduğunu belirlemek için komut satırında kullanılabilecek bir komut, bash komut dosyası, python komut dosyası veya komut dizisi var mı? Gibi bir şey:

if <some code> then
    echo Big Endian
else
    echo Little Endian
fi

Yoksa sistemin hangi işlemciyi kullandığını belirlemek ve Endian'larını belirlemek için buna devam etmek daha mı basit?


İşte perl kullanan çözüm: stackoverflow.com/questions/2610849/…
slu

Yanıtlar:


110

Büyük Bir Endian Sisteminde (SPARC'da Solaris)

$ echo -n I | od -to2 | head -n1 | cut -f2 -d" " | cut -c6 

0

Küçük bir endian sisteminde (Linux x86'da)

$ echo -n I | od -to2 | head -n1 | cut -f2 -d" " | cut -c6 

1


Yukarıdaki çözüm zekicedir ve Linux * 86 ve Solaris Sparc için harikadır.

AIX / Power ve HPUX / Itanium üzerinde de çalışan, sadece kabuklu (Perl'siz) bir çözüme ihtiyacım vardı. Maalesef son ikisi hoş görünmüyor: AIX "6" yazıyor ve HPUX boş bir satır veriyor.

Çözümünüzü kullanarak, tüm bu Unix sistemlerinde çalışan bir şey yapmayı başardım:

$ echo I | tr -d [:space:] | od -to2 | head -n1 | awk '{print $2}' | cut -c6

Birinin gönderdiği Python çözümü ile ilgili olarak, JVM her şeye Büyük gibi davrandığından Jython'da çalışmaz. Herhangi biri Jython'da çalışmasını sağlayabilirse, lütfen gönderin!

Ayrıca, bunu buldum, ki bu, çeşitli platformların eskiliğini açıklar. Bazı donanım, O / S’nin seçtiği seçeneğe bağlı olarak her iki modda da çalışabilir: http://labs.hoffmanlabs.com/node/544


Awk kullanacaksanız, bu satır basitleştirilebilir:

echo -n I | od -to2 | awk '{ print substr($2,6,1); exit}'

'Od' olmayan (OpenWrt) küçük Linux kutuları için 'hexdump' ı deneyin:

echo -n I | hexdump -o | awk '{ print substr($2,6,1); exit}'

2
Bu arada I, bir küçük harf l(ell) yerine bir büyük harf (göz) .
Dennis Williamson,

1
(Solaris) -> (Solaris, Sparc), ancak Sparc> = V9 bi endian.
Cristian Ciupitu

1
Nasıl çalıştığını açıklamak ister misiniz?
Massimo

Bu Android'de (Nexus 5) çalışmıyor gibi görünüyor. Emin değilim neden ...
wjandrea

printf "\x1" | od -to2 | awk 'NR==1{print$2==1}'
Kaz

35

Oldukça yeni bir Linux makinesindeyseniz (2012'den sonra herhangi bir şey varsa)lscpu şimdi bu bilgileri içerir:

$ lscpu | grep Endian
Byte Order:            Little Endian

Bu, lscpuFedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04'te bulunan 2.19 sürümüne eklendi .

Unix.SE'deki bu müthiş cevaptan bu cevabı bulduğuma dikkat edin . Bu cevabın çok fazla alakalı bilgisi var, bu yazı sadece bir özeti.


31

İşte daha zarif bir python tek satırlı komut dosyası

python -c "import sys;sys.exit(0 if sys.byteorder=='big' else 1)"

çıkış kodu 0büyük endian ve 1küçük endian anlamına gelir

ya da sadece değiştirmek sys.exitiçin printyazdırılabilir bir çıkış için


4
Bu, Python 2.4.x çalıştıran RHEL 5.x / CentOS 5.x sistemlerinde çalışmaz. İşte bir düzeltme:python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
JPaget

10

Ana cevap biraz kullanarak basitleştirilebilir awk:

Big Endian sisteminde (Solaris, SPARC)

$ echo -n I | od -to2 | awk 'FNR==1{ print substr($2,6,1)}'
0

Küçük Endian sisteminde (Linux, Intel)

$ echo -n I | od -to2 | awk 'FNR==1{ print substr($2,6,1)}'
1

Yeni Linux Çekirdekleri

Util-linux paketinin 2.19 sürümünden itibaren komut lscpu, Endianness ile ilgili bir alan da dahil olmak üzere başladı. Şimdi bunu öğrenmek için bu komutu kullanabilirsiniz:

$ lscpu | grep -i byte
Byte Order:            Little Endian

Bu, Ubuntu 12.10 ve CentOS 6'da onaylandı. Bu yüzden çoğu 3.0+ Linux Çekirdeğinin bunu sunduğunu varsaymak isterim.

Debian / Ubuntu sistemlerinde, bu komutu ne zaman kullanılacağından emin olmadan da kullanabilirsiniz:

$ dpkg-architecture | grep -i end
DEB_BUILD_ARCH_ENDIAN=little
DEB_HOST_ARCH_ENDIAN=little

Referanslar


9

Bu Python betiği sizin için çalışmalıdır:

#!/usr/bin/env python
from struct import pack
if pack('@h', 1) == pack('<h', 1):
    print "Little Endian"
else:
    print "Big Endian"

4
Bir astar: python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))". Çıkış kodu büyük endian için 0, küçük endian için 1'dir.
Cristian Ciupitu

7
python -c "import sys; print(sys.byteorder)"

Sistemin soyunu basardı.


6

Sisteminizin doğruluğunu belirlemek için ELF dosya biçiminden yararlanabilirsiniz. Örneğin, keyfi bir ELF dosyasının ilk altı baytını hex olarak yazdırın:

xxd -c 1 -l 6 /bin/ls

0000000: 7f . 0000001: 45 E 0000002: 4c L 0000003: 46 F 0000004: 02 . 0000005: 01 .

Son satır (altmış bayt) 01 ise, ELF formatına göre , 01 küçük endian ve 02 büyük endian.

Bir yok varsa xxdda kutuyu (ve busybox var), bu deneyin:

hexdump -s 5 -n 1 -C /bin/busybox


Sanırım keyfi bir ELF demek istiyorsun ... Kabuk komut dosyaları, perl, python vb. Dahil diğer çalıştırılabilir türler olduğu için Aksi halde yanlış olduğunuzu söylememek - sadece diğer çalıştırılabilir türlerin olduğunu hatırlamaya değer olduğunu söylemek (ve ilgi için kod metin segmentinde olduğundan eski metin dosyası meşgul hatasıdır).
Pryftan

1
@Pryftan Buna dikkat çektiğiniz için teşekkürler. Düzeltildi!
Tong Zhou

@TongZhou Hoşgeldiniz; yardım etmekten mutluluk!
Pryftan

Korku veren! Meşgul kutusu tabanlı gömülü işletim sistemlerinde çalışmak için ilk yöntem.
ogurets

3

Jython'da yapmanın bir yolunu buldum. Jython (JVM'deki Python) bir VM'de çalıştığından, donanımdan bağımsız olarak her zaman büyük endian bildirir.

Bu çözüm Linux, Solaris, AIX ve HPUX için çalışıyor. Windows'ta test etmedim:

    from java.lang import System
    for property, value in dict(System.getProperties()).items():
        if property.endswith('cpu.endian'):
            return value

2

ELF formatını temel alan tek satırlık bir komut:
hexdump -s 5 -n 1 /bin/sh


Düzenleme: -n 1, üzgünüm;)
fae

1
Bu aynı zamanda sizinkinden daha fazla ayrıntı sağlayan önceki bir cevapla aynı yöntemdir .
kasperd

0

Biraz farklı gereksinim: Derleme hedef makinesinin kod çalıştırmadan bit veya küçük endian olup olmadığını belirlemek için bir program build configure betiğinde böyle bir teste ihtiyacım var . Script #define HAVE_LITTLE_ENDIAN 1bir config.hbaşlığa veya başka bir başlığa bırakılmalıdır #define HAVE_LITTLE_ENDIAN 0.

Derleme hedef makinesi, derleme makinesinden farklı olabilir, çünkü çapraz derleme yapabiliriz; bu da testin neden derlenmiş bir kod çalıştırmayı denememesi gerektiğini açıklar. printfCevabı yayan bir ifade ile küçük bir C programının olması söz konusu değildir.

Muhtemel bir çözüm budur. Bunu conftest.ciçeren bir dosya üretiyoruz :

#define USPELL(C0, C1, C2, C3) \                                             
  ((unsigned) C0 << 24 | \                                              
   (unsigned) C1 << 16 | \                                              
   (unsigned) C2 << 8 | (unsigned) C3)                                       

unsigned x[6] = {                                                       
  0,                                                                         
  USPELL('L', 'I', 'S', 'P'),                                                
  USPELL('U', 'N', 'I', 'X'),                                                
  USPELL('C', 'O', 'R', 'E'),                                                
  USPELL('D', 'W', 'I', 'M'),                                                
  0                                                                          
};

Şimdi, bunu conftest.okullanmak için derledik:

$ /path/to/cross-compiling/cc conftest.c -c

Sonra koşuyoruz:

$ strings conftest.o
PSILXINUEROCMIWD

Dize PSILXINUEROCMIWDoluşursa, hedef küçük-endian. Dize LISPUNIXCOREDWIMoluşursa, büyük endian. Her iki dize de ortaya çıkmazsa veya daha da şaşırtıcı bir şekilde, ikisi de olmazsa, test başarısız olmuştur.

Bu yaklaşım işe yarıyor, çünkü programda hesaplanan "fourcc" sabitleri, birbirinden bağımsız olarak aynı tam sayıları belirten, makineden bağımsız değerlere sahip. Nesne dosyasındaki depo gösterimleri, hedef sistemin bütünlüğünü izler ve bu, altındaki karakter tabanlı görünümle görülebilir strings.

İki sıfır koruma kelimesi, dizenin izole edilmesini sağlar. Bu kesinlikle gerekli değildir, ancak aradığımız dizginin başka bir dizgeye gömülmemesini sağlar, yani stringsonu bir satırda tek başına çıkartacaktır.

PS USPELLmakrosu argüman eklerini parantez içine almaz, çünkü tekrar kullanım için değil, bu özel amaç için hazırlanmış.


Tüm projeler için gerekli değil ama autoconf / automake bu çeke sahip değil mi? Projelerim kendi Makefiles'imi yapabileceğim her zaman yeterince küçüktür (her zaman temel olmasa da), bu yüzden gerektiğinde bazı değişiklikler yapmaktan başka araçlar da bilmiyorum ve genel arayüz ... ama bunların tespit edilip edilmediğini merak ediyorum. Belki de ihtiyacın olsa bile ihtiyacın yoktu, sadece olasılığı ortaya çıkarabileceğimi düşündüm.
Pryftan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.