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