Як сказати, чи є система Linux великим ендіаном чи мало ендіаном?


91

Я знаю, що певні процесори - Big Endian, а інші - Little Endian. Але чи є команда, bash-скрипт, сценарій python або ряд команд, які можна використовувати в командному рядку, щоб визначити, чи є система Big Endian або Little Endian? Щось на зразок:

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

Або простіше просто визначити, який процесор використовує система, і перейти до цього, щоб визначити його Endianess?


Ось рішення з допомогою Perl: stackoverflow.com/questions/2610849 / ...
трясовина

Відповіді:


110

Про систему Big Endian (Solaris на SPARC)

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

0

На маленькій ендіанській системі (Linux на x86)

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

1


Наведене вище рішення є розумним і чудово працює для Linux * 86 та Solaris Sparc.

Мені знадобилося лише для оболонки (без Perl) рішення, яке також працювало на AIX / Power та HPUX / Itanium. На жаль, останні два не грають добре: AIX повідомляє "6", а HPUX дає порожній рядок.

Використовуючи ваше рішення, я зміг створити щось, що працювало на всіх цих системах Unix:

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

Щодо рішення Python, який хтось розмістив, воно не працює в Jython, оскільки JVM сприймає все як велике. Якщо хтось може змусити його працювати в Jython, будь ласка, напишіть!

Також я виявив це, що пояснює витривалість різних платформ. Деякі апаратні засоби можуть працювати в будь-якому режимі залежно від того, що вибрано O / S: http://labs.hoffmanlabs.com/node/544


Якщо ви збираєтесь використовувати awk, цей рядок можна спростити до:

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

Для невеликих скриньок Linux, у яких немає "od" (скажімо, OpenWrt), спробуйте "hexdump":

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

2
Це, до речі, верхній регістр I(око), а не нижній регістр l(ell).
Денніс Вільямсон

1
(Solaris) -> (Solaris, Sparc), хоча Sparc> = V9 є bi endian.
Крістіан Цюпіту

1
Хочете пояснити, як це працює?
Массімо

Схоже, це не працює на Android (Nexus 5). Не впевнений, чому ...
wjandrea

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

35

Якщо ви перебуваєте на досить недавній машині Linux (більшість всього після 2012 року), то lscpuтепер вона містить цю інформацію:

$ lscpu | grep Endian
Byte Order:            Little Endian

Це було додано lscpuу версії 2.19, яка знаходиться у Fedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04.

Зверніть увагу , що я знайшов цю відповідь від цього приголомшливого відповіді на Unix.SE . Ця відповідь має багато відповідної інформації, ця публікація - лише її короткий виклад.


31

Ось більш елегантний однорядковий сценарій пітона

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

вихідний код 0означає великий ендіан і 1означає маленький ендіан

або просто змінити sys.exitна printдля друку


4
Це не працюватиме на системах RHEL 5.x / CentOS 5.x, на яких працює Python 2.4.x. Ось виправлення:python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
JPaget

10

Основну відповідь можна трохи спростити, використовуючи awk:

Про систему Big Endian (Solaris, SPARC)

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

У системі Little Endian (Linux, Intel)

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

Новіші ядра Linux

З версії 2.19 пакету util-linux команда lscpuпочала включати поле, пов’язане з Endianness. Отже, тепер ви можете просто скористатися цією командою, щоб дізнатися це:

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

Це було підтверджено на Ubuntu 12.10 та CentOS 6. Тож я б хотів припустити, що більшість ядер 3.0+ Linux зараз пропонують це.

У системах Debian / Ubuntu ви також можете використовувати цю команду, не знаючи, коли вона стане доступною:

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

Список літератури


9

Цей сценарій Python повинен працювати для вас:

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

4
Один лайнер: python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))". Код виходу 0 для великого ендіана і 1 для маленького ендіана.
Крістіан Цюпіту


6

Ви можете скористатися форматом файлу ELF, щоб визначити небезпечність вашої системи. Наприклад, надрукуйте перші шість байтів довільного файлу ELF у шістнадцятковій формі:

xxd -c 1 -l 6 /bin/ls

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

Якщо останній рядок (шестибайтний байт) дорівнює 01, відповідно до формату ELF , 01 - мало ендіан, а 02 - великий ендіан.

Якщо у вас немає xxdкоробки (і у вас є зайнята скринька), спробуйте це:

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


Я думаю, ви маєте на увазі довільний ELF ... Оскільки є й інші виконувані типи, включаючи скрипти оболонки, perl, python тощо. Хоча, не кажучи, що ви помиляєтесь інакше - просто кажучи, що варто пам’ятати, що існують і інші виконувані типи (і за інтересом код знаходиться в текстовому сегменті, отже стара помилка зайнятого текстового файлу).
Прифтан

1
@Pryftan Дякую за вказівку на це. Виправлено!
Тонг Чжоу

@TongZhou Ласкаво просимо; рада допомогти!
Прифтан

Дивовижно! Перший метод роботи для вбудованих ОС на основі заняття.
огурець

3

Я знайшов спосіб це зробити в Jython. Оскільки Jython (Python на JVM) працює на VM, він завжди повідомляє про великий ендіан, незалежно від обладнання.

Це рішення працює для Linux, Solaris, AIX та HPUX. Не пройшли тестування в Windows:

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

2

Однорядкова команда на основі формату ELF:
hexdump -s 5 -n 1 /bin/sh


Редагувати: -n 1, вибачте;)
fee

1
Це точно такий же спосіб, як і попередня відповідь , який також надав більше деталей, ніж ваш.
kasperd

0

Трохи інша вимога: мені потрібен такий тест у скрипті конфігурації побудови програми, щоб визначити, чи є цільова машина компіляції бітною або мало ендіанською, без виконання коду . Сценарій повинен зберігатись #define HAVE_LITTLE_ENDIAN 1у config.hзаголовку чи іншому #define HAVE_LITTLE_ENDIAN 0.

Цільова машина компіляції може відрізнятися від машини збирання, оскільки ми можемо перетинати компіляцію, що також пояснює, чому тест не повинен намагатися запустити будь-який компільований код. Немає сумніву, щоб мати невелику програму С із printfзаявою, яка випилює відповідь.

Можливе рішення - це. Ми генеруємо файл, conftest.cякий називається, який містить це:

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

Тепер ми компілюємо це за conftest.oдопомогою:

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

Потім ми запускаємо:

$ strings conftest.o
PSILXINUEROCMIWD

Якщо рядок PSILXINUEROCMIWDтрапляється, ціль є малопомітною. Якщо рядок LISPUNIXCOREDWIMтрапляється, він є великим ендіаном. Якщо не трапляється жодна рядок або, що ще більше дивно, те й інше, тест не вдався.

Цей підхід працює тому, що константи "чотирьох куб", обчислені в програмі, мають незалежні від машини значення, що позначають однакові цілі числа незалежно від витривалості. Їх представлення на зберігання в файлі об'єктів слід за витримкою цільової системи, і це видно через представлення на основі символів в розділі strings.

Два слова з нульовим захистом забезпечують ізоляцію рядка. Це не є строго необхідним, але це гарантує, що рядок, яку ми шукаємо, не вбудовується в якусь іншу рядок, тобто означає, що вона stringsвиведе її на рядок сама по собі.

PS USPELLмакрос не вкладає в дужки вставки аргументів, оскільки він створений для цієї конкретної мети, а не для повторного використання.


Мало того, що це потрібно для всіх проектів, але чи не має автоконф / автоматична перевірка? Мої проекти завжди досить малі, де я можу зробити власні Makefiles (хоча і не завжди базові), тому я не знаю тих інструментів, крім внесення змін, коли це необхідно, і загальний інтерфейс. Але мені цікаво, чи є у них виявлення. Можливо, він вам не потрібен, навіть якщо він це робить, я просто подумав, що я викину можливість.
Прифтан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.