Como saber se um sistema Linux é big endian ou little endian?

83

Eu sei que certos processadores são Big Endian e outros são Little Endian. Mas existe um comando, um script bash, um script python ou uma série de comandos que podem ser usados na linha de comando para determinar se um sistema é Big Endian ou Little Endian? Algo como:

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

Ou é mais simples determinar apenas qual processador o sistema está usando e usá-lo para determinar seu Endianess?

    
por Jake Wilson 23.07.2010 / 18:58

10 respostas

102

Em um Big Endian-System (Solaris no SPARC)

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

0

Em um pequeno sistema endian (Linux em x86)

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

1

A solução acima é inteligente e funciona muito bem para o Linux * 86 e Solaris Sparc.

Eu precisava de uma solução somente shell (sem Perl) que também funcionasse no AIX / Power e no HPUX / Itanium. Infelizmente os dois últimos não são bons: o AIX informa "6" e o HPUX dá uma linha vazia.

Usando sua solução, consegui criar algo que funcionasse em todos esses sistemas Unix:

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

Com relação à solução Python que alguém postou, ela não funciona no Jython porque a JVM trata tudo como Big. Se alguém puder fazê-lo funcionar no Jython, por favor poste!

Além disso, eu encontrei isso, o que explica o endianness de várias plataformas. Alguns hardwares podem operar nos dois modos, dependendo do que o O / S selecionar: link

Se você for usar o awk, esta linha pode ser simplificada para:

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

Para pequenas caixas Linux que não têm 'od' (digamos OpenWrt), então tente 'hexdump':

echo -n I | hexdump -o | awk '{ print substr($2,6,1); exit}'
    
por 23.07.2010 / 19:04
29

Aqui está um script de uma linha em Python mais elegante

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

código de saída 0 significa big endian e 1 significa little endian

ou altere apenas sys.exit para print para uma saída imprimível

    
por 21.05.2011 / 22:26
26

Se você estiver em uma máquina Linux bastante recente (quase tudo depois de 2012) , então lscpu agora contém esta informação:

$ lscpu | grep Endian
Byte Order:            Little Endian

Isso foi adicionado a lscpu na versão 2.19, que é encontrada no Fedora > = 17, CentOS > = 6.0, Ubuntu > = 12.04.

Note que encontrei esta resposta de essa ótima resposta no Unix.SE . Essa resposta tem muita informação relevante, este post é apenas um resumo.

    
por 15.06.2014 / 13:26
10

A resposta principal pode ser simplificada usando awk :

Em um sistema Big Endian (Solaris, SPARC)

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

Em um sistema Little Endian (Linux, Intel)

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

Novos Kernels Linux

A partir da versão 2.19 do pacote util-linux, o comando lscpu começou a incluir um campo relacionado ao Endianness. Então agora você pode simplesmente usar este comando para descobrir isso:

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

Isso foi confirmado no Ubuntu 12.10 e no CentOS 6. Então, eu estaria disposto a assumir que a maioria dos 3.0+ Linux Kernels estão oferecendo isso agora.

Nos sistemas Debian / Ubuntu, você também pode usar este comando, não tendo certeza de quando ele se tornou disponível:

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

Referências

por 31.08.2013 / 01:41
9

Este script Python deve funcionar para você:

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

Ele imprimiria o endianess do sistema.

    
por 28.05.2014 / 09:17
4

Você pode aproveitar o formato de arquivo ELF para determinar o endianness do seu sistema. Por exemplo, imprima os primeiros seis bytes de um arquivo ELF arbitrário em hexadecimal:

xxd -c 1 -l 6 /bin/ls

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

Se a última linha (o byte de seis bytes) for 01, de acordo com o formato ELF , 01 é little endian e 02 é grande endian.

Se você não tem um xxd em sua caixa (e tem busybox), tente isto:

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

    
por 15.01.2016 / 19:23
3

Eu encontrei uma maneira de fazer isso no Jython. Como o Jython (Python na JVM) é executado em uma VM, ele sempre relata big endian, independentemente do hardware.

Esta solução funciona para Linux, Solaris, AIX e HPUX. Não testei no Windows:

    from java.lang import System
    for property, value in dict(System.getProperties()).items():
        if property.endswith('cpu.endian'):
            return value
    
por 30.11.2011 / 23:40
2

Um comando de linha única com base no formato ELF:
hexdump -s 5 -n 1 /bin/sh

    
por 01.04.2016 / 13:36
0

Requisito ligeiramente diferente: Eu preciso de um teste como esse em um script de configuração de compilação de programa para determinar se a máquina de destino de compilação é pouco ou pouco endian, sem executar código . O script deve depositar #define HAVE_LITTLE_ENDIAN 1 em um cabeçalho config.h , ou então #define HAVE_LITTLE_ENDIAN 0 .

A máquina de destino de compilação pode ser diferente da máquina de compilação, uma vez que podemos estar em compilação cruzada, o que também explica por que o teste não deve tentar executar nenhum código compilado. Está fora de questão ter um pequeno programa em C com uma instrução printf que cospe a resposta.

Uma possível solução é essa. Nós geramos um arquivo chamado conftest.c que contém isso:

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

Agora, compilamos isso para conftest.o usando:

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

Então nós corremos:

$ strings conftest.o
PSILXINUEROCMIWD

Se a string PSILXINUEROCMIWD ocorrer, o alvo é little-endian. Se a string LISPUNIXCOREDWIM ocorrer, é big-endian. Se nenhuma string ocorre ou, ainda mais surpreendentemente, ambas ocorrem, então o teste falhou.

Essa abordagem funciona porque as constantes "fourcc" calculadas no programa possuem valores independentes da máquina, denotando os mesmos números inteiros, independentemente do endianness. Sua representação de armazenamento no arquivo de objeto segue o endianness do sistema de destino, e isso é visível através da visualização baseada em caracteres em strings .

As duas palavras de proteção zero asseguram que a sequência seja isolada. Isso não é estritamente necessário, mas garante que a string que estamos procurando não esteja embutida em alguma outra string, o que significa que strings irá produzi-la em uma linha por si só.

P.S. a macro USPELL não coloca em parênteses as inserções de argumento porque é criada para essa finalidade específica, não para reutilização.

    
por 26.05.2017 / 02:37