Как определить, является ли система 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/…
slu 15.10.10

Ответы:

110

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

dotancohen
источник
31

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

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

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

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

mchurichi
источник
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 (Солярис, 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 для старшего и младшего порядкового номера.
Кристиан Чиупиту
7
python -c "import sys; print(sys.byteorder)"

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

prembhaskal
источник
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на вашем ящике (и у вас есть busybox), попробуйте это:

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

Тонг Чжоу
источник
Я думаю, что вы имеете в виду произвольный ELF ... Так как существуют другие исполняемые типы, включая сценарии оболочки, perl, python и т. Д. Не говоря уже о том, что вы ошибаетесь, просто скажу, что стоит помнить, что существуют другие исполняемые типы (и для интереса код находится в текстовом сегменте, следовательно, старая ошибка текстового файла занята).
Прифтан
1
@Pryftan Спасибо за указание на это. Исправил это!
Тонг Чжоу
@TongZhou Добро пожаловать; Рад помочь!
Прифтан
Потрясающие! Первый метод для работы со встроенными ОС на основе busybox.
огурец
3

Я нашел способ сделать это в 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
Foo
источник
2

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

феи
источник
Изменить: -n 1, извините;)
fae
1
Это тот же метод, что и в предыдущем ответе , который также предоставил больше деталей, чем ваш.
kasperd
0

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

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

Kaz
источник
Не то чтобы это было необходимо для всех проектов, но разве autoconf / automake не имеет этой проверки? Мои проекты всегда достаточно малы, чтобы я мог создавать свои собственные Make-файлы (хотя и не всегда базовые), поэтому я не знаю этих инструментов, кроме внесения некоторых изменений, когда это необходимо, и общего интерфейса ... но мне интересно, есть ли у них обнаружение. Возможно, вам это не нужно, даже если оно и есть, просто подумал, что я могу выбросить эту возможность
Прифтан