Назад | Перейти на главную страницу

Как определить, является ли система Linux прямым или прямым порядком байтов?

Я знаю, что некоторые процессоры имеют метод Big Endian, а другие - Little Endian. Но есть ли команда, сценарий bash, сценарий python или серия команд, которые можно использовать в командной строке, чтобы определить, является ли система прямым или прямым порядком байтов? Что-то вроде:

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

Или проще просто определить, какой процессор использует система, и использовать его, чтобы определить его Endianess?

В системе с прямым порядком байтов (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, напишите, пожалуйста!

Кроме того, я обнаружил это, что объясняет порядок байтов различных платформ. Некоторое оборудование может работать в любом режиме в зависимости от того, что выбирает операционная система: 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}'

Если вы используете сравнительно новую машину Linux (почти все после 2012 года) затем lscpu теперь содержит эту информацию:

$ lscpu | grep Endian
Byte Order:            Little Endian

Это было добавлено к lscpu в версии 2.19, которая находится в Fedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04.

Обратите внимание, что я нашел этот ответ от этот потрясающий ответ на Unix.SE. В этом ответе много важной информации, этот пост - всего лишь ее краткое изложение.

Вот более элегантный однострочный скрипт на Python

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

код выхода 0 означает большой порядок байтов и 1 означает прямой порядок байтов

или просто изменить sys.exit к print для вывода на печать

Вы можете воспользоваться форматом файла 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 на вашем ящике (и у вас есть busybox), попробуйте следующее:

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

Основной ответ можно немного упростить, используя awk:

В системе с прямым порядком байтов (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 начал включать поле, связанное с порядком байтов. Итак, теперь вы можете просто использовать эту команду, чтобы узнать это:

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

Это было подтверждено в Ubuntu 12.10 и CentOS 6. Поэтому я хотел бы предположить, что большинство ядер Linux 3.0+ теперь предлагают это.

В системах Debian / Ubuntu вы также можете использовать эту команду, не зная, когда она стала доступна:

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

Ссылки

Этот скрипт Python должен работать на вас:

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

Он напечатал бы порядок байтов системы.

Я нашел способ сделать это в Jython. Поскольку Jython (Python на JVM) работает на виртуальной машине, он всегда сообщает обратный порядок байтов независимо от оборудования.

Это решение работает для 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

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

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

Целевая машина компиляции может отличаться от машины сборки, поскольку мы можем выполнять кросс-компиляцию, что также объясняет, почему тест не должен пытаться выполнить какой-либо скомпилированный код. Не может быть и речи о маленькой программе на C с 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 происходит, с прямым порядком байтов. Если ни одна строка не встречается или, что еще более удивительно, появляются обе, значит, тест не удался.

Этот подход работает, потому что константы "fourcc", вычисленные в программе, имеют машинно-независимые значения, обозначающие одни и те же целые числа независимо от порядка байтов. Их представление хранилища в объектном файле соответствует порядку байтов целевой системы, и это видно через символьное представление под strings.

Два нулевых защитных слова обеспечивают изоляцию строки. В этом нет строгой необходимости, но это гарантирует, что искомая строка не встроена в какую-либо другую строку, что означает, что strings выведет его в отдельной строке.

P.S. то USPELL макрос не заключен в скобки для вставки аргументов, потому что он создан для этой конкретной цели, а не для повторного использования.