¿Cómo saber si un sistema Linux es big endian o little endian?

91

Sé que ciertos procesadores son Big Endian y otros son Little Endian. Pero, ¿hay un comando, un script bash, un script python o una serie de comandos que se puedan usar en la línea de comando para determinar si un sistema es Big Endian o Little Endian? Algo como:

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

¿O es más simple determinar qué procesador está usando el sistema e ir con eso para determinar su Endianess?

Jake Wilson
fuente
Aquí está la solución usando perl: stackoverflow.com/questions/2610849/…
slu

Respuestas:

110

En un sistema Big Endian (Solaris en SPARC)

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

0 0

En un pequeño sistema endian (Linux en x86)

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

1


La solución anterior es inteligente y funciona muy bien para Linux * 86 y Solaris Sparc.

Necesitaba una solución de shell (sin Perl) que también funcionara en AIX / Power y HPUX / Itanium. Desafortunadamente, los dos últimos no juegan bien: AIX informa "6" y HPUX da una línea vacía.

Usando su solución, pude crear algo que funcionó en todos estos sistemas Unix:

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

Con respecto a la solución de Python que alguien publicó, no funciona en Jython porque la JVM trata todo como Big. Si alguien puede hacer que funcione en Jython, ¡publíquelo!

Además, encontré esto, lo que explica la resistencia de varias plataformas. Parte del hardware puede funcionar en cualquier modo, según lo que seleccione la O / S: http://labs.hoffmanlabs.com/node/544


Si va a usar awk, esta línea se puede simplificar para:

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

Para pequeñas cajas de Linux que no tienen 'od' (digamos OpenWrt), entonces intente 'hexdump':

echo -n I | hexdump -o | awk '{ print substr($2,6,1); exit}'
krissi
fuente
2
Por cierto, es una mayúscula I(ojo) en lugar de una minúscula l(ell).
Dennis Williamson
1
(Solaris) -> (Solaris, Sparc), aunque Sparc> = V9 es bi endian.
Cristian Ciupitu
1
¿Te importaría explicar cómo funciona?
Massimo
Esto no parece funcionar en Android (Nexus 5). No estoy seguro de por qué ...
wjandrea
printf "\x1" | od -to2 | awk 'NR==1{print$2==1}'
Kaz
35

Si está en una máquina Linux bastante reciente (casi todo después de 2012) , lscpuahora contiene esta información:

$ lscpu | grep Endian
Byte Order:            Little Endian

Esto se agregó a la lscpuversión 2.19, que se encuentra en Fedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04.

Tenga en cuenta que he encontrado esta respuesta de esta respuesta excelente en Unix.SE . Esa respuesta tiene mucha información relevante, esta publicación es solo un resumen.

dotancohen
fuente
31

Aquí hay un script de una línea más elegante de Python

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

código de salida 0significa big endian y 1little endian

o simplemente cambie sys.exita printpara una salida imprimible

mchurichi
fuente
44
Esto no funcionará en los sistemas RHEL 5.x / CentOS 5.x que ejecutan Python 2.4.x. Aquí hay una solución:python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
JPaget
10

La respuesta principal se puede simplificar ligeramente usando awk:

En un sistema Big Endian (Solaris, SPARC)

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

En un sistema Little Endian (Linux, Intel)

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

Kernels Linux más nuevos

A partir de la versión 2.19 del paquete util-linux, el comando lscpucomenzó incluyendo un campo relacionado con Endianness. Así que ahora puedes simplemente usar este comando para descubrir esto:

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

Esto se ha confirmado en Ubuntu 12.10 y CentOS 6. Por lo tanto, estaría dispuesto a asumir que la mayoría de los Kernels Linux 3.0+ están ofreciendo esto.

En los sistemas Debian / Ubuntu también puede usar este comando, sin saber cuándo estuvo disponible:

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

Referencias

slm
fuente
9

Este script de Python debería funcionar para usted:

#!/usr/bin/env python
from struct import pack
if pack('@h', 1) == pack('<h', 1):
    print "Little Endian"
else:
    print "Big Endian"
Dennis Williamson
fuente
44
Un revestimiento: python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))". El código de salida es 0 para big endian y 1 para little endian.
Cristian Ciupitu
7
python -c "import sys; print(sys.byteorder)"

Imprimiría la endianess del sistema.

prembhaskal
fuente
6

Puede aprovechar el formato de archivo ELF para determinar la resistencia de su sistema. Por ejemplo, imprima los primeros seis bytes de un archivo ELF arbitrario en hexadecimal:

xxd -c 1 -l 6 /bin/ls

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

Si la última línea (el byte seseado) es 01, según el formato ELF , 01 es little endian y 02 es big endian.

Si no tiene uno xxden su caja (y tiene busybox), intente esto:

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

Tong Zhou
fuente
Creo que te refieres a un ELF arbitrario ... Dado que hay otros tipos ejecutables, incluidos scripts de shell, perl, python, etc. Sin embargo, no digo que estés equivocado, solo digo que vale la pena recordar que hay otros tipos ejecutables (y por interés, el código está en el segmento de texto, de ahí el error de ocupado del archivo de texto antiguo).
Pryftan
1
@Pryftan Gracias por señalar eso. Corregido!
Tong Zhou
@TongZhou Bienvenido; ¡Me alegra ser de ayuda!
Pryftan
¡Increíble! Primer método para trabajar para sistemas operativos integrados basados ​​en busybox.
ogurets
3

Encontré una manera de hacerlo en Jython. Dado que Jython (Python en la JVM) se ejecuta en una máquina virtual, siempre informa big endian, independientemente del hardware.

Esta solución funciona para Linux, Solaris, AIX y HPUX. No he probado en Windows:

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

Un comando de una sola línea basado en el formato ELF:
hexdump -s 5 -n 1 /bin/sh

fae
fuente
Editar: -n 1, lo siento;)
fae
1
Este es exactamente el mismo método que una respuesta anterior , que también proporcionó más detalles que los suyos.
Kasperd 01 de
0

Requisito ligeramente diferente: necesito una prueba como esta en un script de configuración de compilación del programa para determinar si la máquina de compilación de destino es bit o little endian, sin ejecutar código . El script debe depositarse #define HAVE_LITTLE_ENDIAN 1en un config.hencabezado, o de lo contrario #define HAVE_LITTLE_ENDIAN 0.

La máquina de compilación de destino puede ser diferente de la máquina de compilación, ya que podemos realizar una compilación cruzada, lo que también explica por qué la prueba no debe intentar ejecutar ningún código compilado. Es imposible tener un pequeño programa en C con una printfdeclaración que escupe la respuesta.

Una posible solución es esta. Generamos un archivo llamado conftest.cque contiene esto:

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

Ahora, compilamos esto para conftest.ousar:

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

Luego corremos:

$ strings conftest.o
PSILXINUEROCMIWD

Si se PSILXINUEROCMIWDproduce la cadena , el objetivo es little-endian. Si se LISPUNIXCOREDWIMproduce la cadena , es big-endian. Si no se produce ninguna cadena o, lo que es más sorprendente, ambas lo hacen, entonces la prueba ha fallado.

Este enfoque funciona porque las constantes "fourcc" calculadas en el programa tienen valores independientes de la máquina, que denotan los mismos enteros independientemente de la endianidad. Su representación de almacenamiento en el archivo de objeto sigue la endianness del sistema de destino, y eso es visible a través de la vista basada en caracteres debajo strings.

Las dos palabras de protección cero aseguran que la cadena esté aislada. Eso no es estrictamente necesario, pero asegura que la cadena que estamos buscando no esté incrustada en alguna otra cadena, lo que significa que la stringsgenerará en una línea por sí misma.

PD: la USPELLmacro no hace paréntesis de las inserciones de argumentos porque está diseñada para este propósito específico, no para su reutilización.

Kaz
fuente
No es que sea necesario para todos los proyectos, pero ¿autoconf / automake no tiene esta verificación? Mis proyectos siempre son lo suficientemente pequeños donde puedo hacer mis propios Makefiles (aunque no siempre son básicos), por lo que realmente no conozco esas herramientas aparte de hacer algunas modificaciones cuando sea necesario y la interfaz general ... pero me pregunto si tienen detección. Tal vez no lo necesitaras, incluso si lo necesita, solo pensé que descartaría la posibilidad.
Pryftan