web-dev-qa-db-fra.com

Comment savoir si un système Linux est big endian ou little endian?

Je sais que certains processeurs sont Big Endian et d'autres sont Little Endian. Mais existe-t-il une commande, un script bash, un script python ou une série de commandes qui peuvent être utilisés sur la ligne de commande pour déterminer si un système est Big Endian ou Little Endian? Quelque chose comme:

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

Ou est-il plus simple de simplement déterminer quel processeur le système utilise et de le suivre pour déterminer son endianess?

95
Jake Wilson

Sur un système Big Endian (Solaris sur SPARC)

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

Sur un petit système endian (Linux sur x86)

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

1


La solution ci-dessus est intelligente et fonctionne très bien pour Linux * 86 et Solaris Sparc.

J'avais besoin d'une solution Shell uniquement (pas de Perl) qui fonctionnait également sur AIX/Power et HPUX/Itanium. Malheureusement, les deux derniers ne jouent pas à Nice: AIX rapporte "6" et HPUX donne une ligne vide.

En utilisant votre solution, j'ai pu créer quelque chose qui fonctionnait sur tous ces systèmes Unix:

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

Concernant la solution Python publiée par quelqu'un, elle ne fonctionne pas en Jython car la JVM traite tout comme Big. Si quelqu'un peut le faire fonctionner en Jython, merci de poster!

J'ai également trouvé cela, ce qui explique l'endianité de différentes plateformes. Certains matériels peuvent fonctionner dans l'un ou l'autre mode selon ce que l'O/S sélectionne: http://labs.hoffmanlabs.com/node/544


Si vous allez utiliser awk, cette ligne peut être simplifiée pour:

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

Pour les petites boîtes Linux qui n'ont pas 'od' (disons OpenWrt) alors essayez 'hexdump':

echo -n I | hexdump -o | awk '{ print substr($2,6,1); exit}'
114
krissi

Si vous êtes sur une machine Linux assez récente (presque tout après 2012) alors lscpu contient maintenant ces informations:

$ lscpu | grep Endian
Byte Order:            Little Endian

Cela a été ajouté à lscpu dans la version 2.19, qui se trouve dans Fedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04.

Notez que j'ai trouvé cette réponse de cette formidable réponse sur Unix.SE . Cette réponse contient beaucoup d'informations pertinentes, ce message n'en est qu'un résumé.

40
dotancohen

Voici un script plus élégant python d'une ligne

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

code de sortie 0 signifie big endian et 1 signifie petit endian

ou changez simplement sys.exit à print pour une sortie imprimable

32
mchurichi

Vous pouvez profiter du format de fichier ELF pour déterminer l'endianité de votre système. Par exemple, imprimez les six premiers octets d'un fichier ELF arbitraire en hexadécimal:

xxd -c 1 -l 6 /bin/ls

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

Si la dernière ligne (l'octet à six) est 01, selon format ELF , 01 est petit endian et 02 est gros endian.

Si vous n'avez pas de xxd sur votre box (et avez une busybox), essayez ceci:

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

10
Tong Zhou

La réponse principale peut être légèrement simplifiée en utilisant awk:

Sur un système Big Endian (Solaris, SPARC)

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

Sur un système Little Endian (Linux, Intel)

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

Nouveaux noyaux Linux

Depuis la version 2.19 du paquet util-linux, la commande lscpu a commencé à inclure un champ lié à Endianness. Alors maintenant, vous pouvez simplement utiliser cette commande pour le découvrir:

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

Cela a été confirmé sur Ubuntu 12.10 et CentOS 6. Je serais donc prêt à supposer que la plupart des noyaux Linux 3.0+ offrent maintenant cela.

Sur les systèmes Debian/Ubuntu, vous pouvez également utiliser cette commande, sans savoir quand elle sera disponible:

$ dpkg-architecture | grep -i end
DEB_BUILD_Arch_ENDIAN=little
DEB_Host_Arch_ENDIAN=little

Références

10
slm

Ce script Python devrait fonctionner pour vous:

#!/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)"

Cela imprimerait l'endianité du système.

7
prembhaskal

J'ai trouvé un moyen de le faire en Jython. Étant donné que Jython (Python sur la JVM) s'exécute sur une machine virtuelle, il signale toujours un gros endian, quel que soit le matériel.

Cette solution fonctionne pour Linux, Solaris, AIX et HPUX. N'ont pas testé sous Windows:

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

Une commande sur une seule ligne basée sur le format ELF:
hexdump -s 5 -n 1 /bin/sh

2
fae

Exigence légèrement différente: j'ai besoin d'un test comme celui-ci dans un script de configuration de programme pour déterminer si compiler la machine cible est un bit ou un petit endian, sans exécuter de code. Le script doit déposer #define HAVE_LITTLE_ENDIAN 1 dans une config.h en-tête, sinon #define HAVE_LITTLE_ENDIAN 0.

La machine cible de compilation peut être différente de la machine de génération, car nous pouvons effectuer une compilation croisée, ce qui explique également pourquoi le test ne doit pas essayer d'exécuter de code compilé. Il est hors de question d'avoir un petit programme C avec une instruction printf qui crache la réponse.

Voici une solution possible. Nous générons un fichier appelé conftest.c qui contient ceci:

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

Maintenant, nous compilons ceci en conftest.o en utilisant:

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

Ensuite, nous courons:

$ strings conftest.o
PSILXINUEROCMIWD

Si la chaîne PSILXINUEROCMIWD apparaît, la cible est little-endian. Si la chaîne LISPUNIXCOREDWIM apparaît, elle est big-endian. Si aucune chaîne ne se produit ou, plus étonnant encore, les deux le font, le test a échoué.

Cette approche fonctionne parce que les constantes "fourcc" calculées dans le programme ont des valeurs indépendantes de la machine, désignant les mêmes entiers indépendamment de l'endianité. Leur représentation de stockage dans le fichier objet suit l'endianité du système cible, et cela est visible via la vue basée sur les caractères sous strings.

Les deux mots de garde zéro garantissent que la chaîne est isolée. Ce n'est pas strictement nécessaire, mais cela garantit que la chaîne que nous recherchons n'est pas incorporée dans une autre chaîne, ce qui signifie que strings la produira seule sur une ligne.

P.S. la macro USPELL ne met pas entre parenthèses les insertions d'argument car elle est conçue dans ce but spécifique, pas pour une réutilisation.

0
Kaz