Bagaimana cara mengetahui apakah sistem Linux big endian atau little endian?

91

Saya tahu bahwa prosesor tertentu adalah Big Endian dan lainnya adalah Little Endian. Tetapi apakah ada perintah, skrip bash, skrip python, atau serangkaian perintah yang dapat digunakan pada baris perintah untuk menentukan apakah suatu sistem adalah Big Endian atau Little Endian? Sesuatu seperti:

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

Atau apakah lebih sederhana untuk menentukan prosesor apa yang digunakan sistem dan mengikutinya untuk menentukan Endianessnya?

Jake Wilson
sumber
Inilah solusinya menggunakan perl: stackoverflow.com/questions/2610849/…
slu

Jawaban:

110

Pada Sistem Big Endian (Solaris pada SPARC)

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

0

Pada sistem endian kecil (Linux pada x86)

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

1


Solusi di atas pintar dan berfungsi baik untuk Linux * 86 dan Solaris Sparc.

Saya membutuhkan solusi shell-only (no Perl) yang juga bekerja pada AIX / Power dan HPUX / Itanium. Sayangnya dua yang terakhir tidak berfungsi dengan baik: AIX melaporkan "6" dan HPUX memberikan baris kosong.

Menggunakan solusi Anda, saya dapat membuat sesuatu yang bekerja pada semua sistem Unix ini:

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

Mengenai solusi Python yang diposting seseorang, itu tidak berfungsi di Jython karena JVM memperlakukan semuanya sebagai Besar. Jika ada yang bisa membuatnya bekerja di Jython, silakan posting!

Juga, saya menemukan ini, yang menjelaskan endianness dari berbagai platform. Beberapa perangkat keras dapat beroperasi dalam mode mana pun tergantung pada apa yang O / S pilih: http://labs.hoffmanlabs.com/node/544


Jika Anda akan menggunakan awk, baris ini dapat disederhanakan menjadi:

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

Untuk kotak Linux kecil yang tidak memiliki 'od' (katakanlah OpenWrt) kemudian coba 'hexdump':

echo -n I | hexdump -o | awk '{ print substr($2,6,1); exit}'
Krissi
sumber
2
Ngomong-ngomong itu huruf besar I(mata) dan bukan huruf kecil l(ell).
Dennis Williamson
1
(Solaris) -> (Solaris, Sparc), meskipun Sparc> = V9 adalah bi endian.
Cristian Ciupitu
1
Mau jelaskan cara kerjanya?
Massimo
Ini sepertinya tidak berfungsi di Android (Nexus 5). Tidak yakin mengapa ...
wjandrea
printf "\x1" | od -to2 | awk 'NR==1{print$2==1}'
Kaz
35

Jika Anda menggunakan mesin Linux yang cukup baru (sebagian besar setelah 2012) maka lscpusekarang berisi informasi ini:

$ lscpu | grep Endian
Byte Order:            Little Endian

Ini ditambahkan ke lscpudalam versi 2.19, yang ditemukan di Fedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04.

Perhatikan bahwa saya menemukan jawaban ini dari jawaban hebat ini pada Unix.SE . Jawaban itu memiliki banyak informasi yang relevan, posting ini hanyalah ringkasannya.

dotancohen
sumber
31

Berikut ini adalah skrip satu baris python yang lebih elegan

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

kode keluar 0berarti big endian dan 1berarti little endian

atau hanya mengubah sys.exitke printuntuk hasil cetak

mchurichi
sumber
4
Ini tidak akan bekerja pada sistem RHEL 5.x / CentOS 5.x yang menjalankan Python 2.4.x. Ini adalah perbaikan:python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
JPaget
10

Jawaban utama dapat disederhanakan sedikit menggunakan awk:

Pada sistem Big Endian (Solaris, SPARC)

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

Pada sistem Little Endian (Linux, Intel)

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

Kernel Linux yang lebih baru

Pada versi 2.19 dari paket util-linux perintah lscpumulai termasuk bidang yang terkait dengan Endianness. Jadi sekarang Anda bisa menggunakan perintah ini untuk mencari tahu:

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

Ini telah dikonfirmasi pada Ubuntu 12.10 dan CentOS 6. Jadi saya akan berasumsi bahwa kebanyakan kernel Linux 3.0+ sekarang menawarkan ini.

Pada sistem Debian / Ubuntu Anda juga dapat menggunakan perintah ini, tidak yakin kapan itu tersedia:

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

Referensi

slm
sumber
9

Skrip Python ini bisa digunakan untuk Anda:

#!/usr/bin/env python
from struct import pack
if pack('@h', 1) == pack('<h', 1):
    print "Little Endian"
else:
    print "Big Endian"
Dennis Williamson
sumber
4
Satu kapal: python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))". Kode keluar adalah 0 untuk big endian dan 1 untuk little endian.
Cristian Ciupitu
7
python -c "import sys; print(sys.byteorder)"

Itu akan mencetak endianess sistem.

prembhaskal
sumber
6

Anda dapat memanfaatkan format file ELF untuk menentukan tingkat kehabisan sistem Anda. Misalnya, cetak enam byte pertama dari file ELF sembarang dalam hex:

xxd -c 1 -l 6 /bin/ls

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

Jika baris terakhir (byte berenam) adalah 01, menurut format ELF , 01 adalah endian kecil dan 02 adalah big endian.

Jika Anda belum punya xxddi kotak Anda (dan punya kotak sibuk), coba ini:

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

Tong Zhou
sumber
Saya pikir maksud Anda ELF sewenang-wenang ... Karena ada jenis yang dapat dieksekusi lainnya termasuk skrip shell, perl, python, dll. Namun tidak mengatakan Anda salah, hanya mengatakan bahwa perlu diingat bahwa ada jenis yang dapat dieksekusi lainnya (dan untuk kepentingan kode berada di segmen teks maka kesalahan sibuk file teks lama).
Pryftan
1
@Pryftan Terima kasih telah menunjukkannya. Diperbaiki!
Tong Zhou
@ Selamat Datang Selamat Datang; senang bisa membantu!
Pryftan
Luar biasa! Metode pertama yang bekerja untuk embedded OS berbasis busybox.
oguret
3

Saya menemukan cara untuk melakukannya di Jython. Karena Jython (Python pada JVM) berjalan pada VM, selalu melaporkan big endian, terlepas dari perangkat kerasnya.

Solusi ini berfungsi untuk Linux, Solaris, AIX, dan HPUX. Belum diuji pada Windows:

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

Perintah baris tunggal berdasarkan format ELF:
hexdump -s 5 -n 1 /bin/sh

fae
sumber
Sunting: -n 1, maaf;)
fae
1
Ini adalah metode yang sama persis dengan jawaban sebelumnya , yang juga memberikan lebih banyak detail daripada jawaban Anda.
kasperd
0

Persyaratan yang sedikit berbeda: Saya perlu tes seperti ini dalam program build configure script untuk menentukan apakah mesin target kompilasi sedikit atau sedikit endian, tanpa mengeksekusi kode . Script harus disetor #define HAVE_LITTLE_ENDIAN 1ke config.hheader, atau yang lain #define HAVE_LITTLE_ENDIAN 0.

Mesin target kompilasi mungkin berbeda dari mesin build, karena kami mungkin mengkompilasi silang, yang juga menjelaskan mengapa pengujian tidak boleh mencoba menjalankan kode yang dikompilasi. Adalah tidak mungkin untuk memiliki program C kecil dengan printfpernyataan yang mengeluarkan jawabannya.

Solusi yang mungkin adalah ini. Kami menghasilkan file bernama conftest.cyang berisi ini:

#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                                                                          
};

Sekarang, kami kompilasi ini untuk conftest.omenggunakan:

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

Lalu kita jalankan:

$ strings conftest.o
PSILXINUEROCMIWD

Jika string PSILXINUEROCMIWDterjadi, targetnya adalah little-endian. Jika string LISPUNIXCOREDWIMterjadi, itu adalah big-endian. Jika tidak ada senar yang muncul atau, yang lebih mengejutkan, keduanya terjadi, maka pengujian gagal.

Pendekatan ini bekerja karena konstanta "fourcc" yang dihitung dalam program memiliki nilai mesin-independen, menunjukkan bilangan bulat yang sama terlepas dari endianness. Representasi penyimpanan mereka dalam file objek mengikuti endianness dari sistem target, dan itu terlihat melalui tampilan berbasis karakter di bawah strings.

Dua kata nol guard memastikan bahwa string terisolasi. Itu tidak sepenuhnya diperlukan, tetapi memastikan bahwa string yang kita cari tidak tertanam dalam beberapa string lain, yang berarti stringsakan menampilkannya pada sebuah baris dengan sendirinya.

PS USPELLmakro tidak mengurung sisipan argumen karena dibuat untuk tujuan khusus ini, bukan untuk digunakan kembali.

Kaz
sumber
Bukan berarti itu perlu untuk semua proyek tetapi apakah autoconf / automake tidak memiliki pemeriksaan ini? Proyek saya selalu cukup kecil di mana saya dapat membuat Makefile saya sendiri (meskipun tidak selalu dasar) jadi saya tidak benar-benar tahu alat-alat itu selain membuat beberapa modifikasi bila perlu dan antarmuka umum..tapi saya bertanya-tanya apakah mereka memiliki deteksi. Mungkin Anda tidak membutuhkannya bahkan jika itu benar, hanya berpikir saya akan membuang kemungkinan itu.
Pryftan