Làm thế nào để biết một hệ thống Linux là endian lớn hay endian nhỏ?


91

Tôi biết rằng một số bộ xử lý là Big Endian và những bộ khác là Little Endian. Nhưng có một lệnh, bash script, python script hoặc một loạt các lệnh có thể được sử dụng tại dòng lệnh để xác định xem một hệ thống là Big Endian hay Little Endian? Cái gì đó như:

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

Hoặc đơn giản hơn là chỉ cần xác định bộ xử lý nào mà hệ thống đang sử dụng và đi cùng với đó để xác định Endianess của nó?


Đây là giải pháp sử dụng perl: stackoverflow.com/questions/2610849/ từ
slu

Câu trả lời:


110

Trên một hệ thống cuối lớn (Solaris trên SPARC)

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

0

Trên một hệ thống endian nhỏ (Linux trên x86)

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

1


Giải pháp trên rất thông minh và hoạt động tốt cho Linux * 86 và Solaris Sparc.

Tôi cần một giải pháp chỉ vỏ (không có Perl) cũng hoạt động trên AIX / Power và HPUX / Itanium. Thật không may, hai cái cuối cùng không chơi tốt: AIX báo cáo "6" và HPUX đưa ra một dòng trống.

Sử dụng giải pháp của bạn, tôi đã có thể tạo ra thứ gì đó hoạt động trên tất cả các hệ thống Unix này:

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

Về giải pháp Python mà ai đó đã đăng, nó không hoạt động trong Jython vì JVM coi mọi thứ là Lớn. Nếu bất cứ ai có thể làm cho nó hoạt động trong Jython, xin vui lòng gửi!

Ngoài ra, tôi tìm thấy điều này, giải thích sự tồn tại của các nền tảng khác nhau. Một số phần cứng có thể hoạt động ở một trong hai chế độ tùy thuộc vào những gì O / S chọn: http://labs.hoffmanlabs.com/node/544


Nếu bạn định sử dụng awk, dòng này có thể được đơn giản hóa thành:

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

Đối với các hộp Linux nhỏ không có 'od' (giả sử OpenWrt), hãy thử 'hexdump':

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

2
Đó là một chữ hoa I(mắt) chứ không phải chữ thường l(ell).
Dennis Williamson

1
(Solaris) -> (Solaris, Sparc), mặc dù Sparc> = V9 là bi endian.
Cristian Ciupitu

1
Quan tâm để giải thích làm thế nào nó hoạt động?
Massimo

Điều này dường như không hoạt động trên Android (Nexus 5). Không chắc tại sao ...
wjandrea

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

35

Nếu bạn đang sử dụng máy Linux khá gần đây (hầu hết mọi thứ sau năm 2012) thì lscpubây giờ có chứa thông tin này:

$ lscpu | grep Endian
Byte Order:            Little Endian

Điều này đã được thêm vào lscputrong phiên bản 2.19, được tìm thấy trong Fedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04.

Lưu ý rằng tôi tìm thấy câu trả lời này từ câu trả lời tuyệt vời này trên Unix.SE . Câu trả lời đó có rất nhiều thông tin liên quan, bài đăng này chỉ là một bản tóm tắt của nó.


31

Dưới đây là một kịch bản một dòng python thanh lịch hơn

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

mã thoát 0có nghĩa là endian lớn và 1có nghĩa là endian nhỏ

hoặc chỉ thay đổi sys.exitthành printcho một đầu ra có thể in


4
Điều này sẽ không hoạt động trên các hệ thống RHEL 5.x / CentOS 5.x đang chạy Python 2.4.x. Đây là một sửa chữa:python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
JPaget

10

Câu trả lời chính có thể được đơn giản hóa một chút bằng cách sử dụng awk:

Trên hệ thống Big Endian (Solaris, SPARC)

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

Trên hệ thống Little Endian (Linux, Intel)

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

Hạt nhân Linux mới hơn

Kể từ phiên bản 2.19 của gói linux-linux, lệnh lscpubắt đầu bao gồm một trường liên quan đến Endianness. Vì vậy, bây giờ bạn có thể chỉ cần sử dụng lệnh này để tìm hiểu điều này:

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

Điều này đã được xác nhận trên Ubuntu 12.10 và CentOS 6. Vì vậy, tôi sẽ sẵn sàng cho rằng hầu hết các nhân Linux 3.0 trở lên hiện đang cung cấp điều này.

Trên các hệ thống Debian / Ubuntu, bạn cũng có thể sử dụng lệnh này, không chắc chắn khi nào nó có sẵn:

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

Người giới thiệu


9

Kịch bản Python này sẽ phù hợp với bạn:

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

4
Một lớp lót : python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))". Mã thoát là 0 cho endian lớn và 1 cho endian nhỏ.
Cristian Ciupitu

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

Nó sẽ in endianess của hệ thống.


6

Bạn có thể tận dụng định dạng tệp ELF để xác định tuổi thọ của hệ thống. Ví dụ: in sáu byte đầu tiên của tệp ELF tùy ý ở dạng hex:

xxd -c 1 -l 6 /bin/ls

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

Nếu dòng cuối cùng (byte sáu) là 01, theo định dạng ELF , 01 là endian nhỏ và 02 là endian lớn.

Nếu bạn chưa có xxdhộp thư của mình (và không có busybox), hãy thử điều này:

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


Tôi nghĩ bạn có nghĩa là một ELF tùy ý ... Vì có các loại thực thi khác bao gồm các tập lệnh shell, perl, python, v.v. Để quan tâm, mã nằm trong đoạn văn bản do đó lỗi văn bản cũ bị lỗi).
Pryftan

1
@Pryftan Cảm ơn bạn đã chỉ ra điều đó. Đã sửa nó!
Tong Zhou

@TongZhou Chào mừng bạn; Vinh dự khi được giup bạn!
Pryftan

Tuyệt vời! Phương pháp đầu tiên để làm việc cho các hệ điều hành nhúng dựa trên busybox.
ogurets

3

Tôi tìm thấy một cách để làm điều đó trong Jython. Vì Jython (Python trên JVM) chạy trên VM, nó luôn báo cáo endian lớn, bất kể phần cứng.

Giải pháp này hoạt động cho Linux, Solaris, AIX và HPUX. Chưa được thử nghiệm trên Windows:

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

2

Lệnh một dòng dựa trên định dạng ELF:
hexdump -s 5 -n 1 /bin/sh


Chỉnh sửa: -n 1, xin lỗi;)
fae

1
Đây là phương pháp chính xác giống như câu trả lời trước đó , cũng cung cấp nhiều chi tiết hơn của bạn.
kasperd

0

Yêu cầu hơi khác một chút: Tôi cần một thử nghiệm như thế này trong tập lệnh cấu hình chương trình xây dựng chương trình để xác định xem máy đích biên dịch là bit hay endian, mà không cần thực thi mã . Kịch bản phải gửi #define HAVE_LITTLE_ENDIAN 1vào một config.htiêu đề, hoặc nếu không #define HAVE_LITTLE_ENDIAN 0.

Máy đích biên dịch có thể khác với máy xây dựng, vì chúng tôi có thể biên dịch chéo, điều này cũng giải thích tại sao thử nghiệm không được thử chạy bất kỳ mã được biên dịch nào. Không có vấn đề gì khi có một chương trình C nhỏ với một printftuyên bố phun ra câu trả lời.

Một giải pháp có thể là đây. Chúng tôi tạo ra một tệp có tên conftest.cnày:

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

Bây giờ, chúng tôi biên dịch điều này để conftest.osử dụng:

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

Sau đó, chúng tôi chạy:

$ strings conftest.o
PSILXINUEROCMIWD

Nếu chuỗi PSILXINUEROCMIWDxảy ra, mục tiêu là endian nhỏ. Nếu chuỗi LISPUNIXCOREDWIMxảy ra, nó là endian lớn. Nếu không có chuỗi nào xảy ra hoặc, thậm chí đáng kinh ngạc hơn, cả hai đều làm, thì thử nghiệm đã thất bại.

Cách tiếp cận này hoạt động vì các hằng số "bốncc" được tính toán trong chương trình có các giá trị độc lập với máy, biểu thị các số nguyên giống nhau bất kể tuổi thọ. Biểu diễn lưu trữ của chúng trong tệp đối tượng tuân theo độ bền của hệ thống đích và được hiển thị thông qua chế độ xem dựa trên ký tự bên dưới strings.

Hai từ bảo vệ bằng không đảm bảo rằng chuỗi được cách ly. Điều đó không thực sự cần thiết, nhưng nó đảm bảo rằng chuỗi mà chúng ta đang tìm kiếm không được nhúng vào một số chuỗi khác, có nghĩa là nó stringssẽ tự xuất nó trên một dòng.

PS USPELLmacro không ngoặc đơn cho các phần chèn thêm đối số vì nó được tạo ra cho mục đích cụ thể này, không phải để sử dụng lại.


Không phải là nó cần thiết cho tất cả các dự án nhưng autoconf / automake không có kiểm tra này? Các dự án của tôi luôn đủ nhỏ để tôi có thể tự tạo Makefiles (mặc dù không phải lúc nào cũng cơ bản) vì vậy tôi không thực sự biết những công cụ đó ngoài việc thực hiện một số sửa đổi khi cần thiết và giao diện chung..nhưng tôi tự hỏi liệu chúng có phát hiện được không. Có lẽ bạn không cần nó ngay cả khi nó có, chỉ cần nghĩ rằng tôi sẽ bỏ qua khả năng đó.
Pryftan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.