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?
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}'
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é.
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
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
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
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
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.
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
Une commande sur une seule ligne basée sur le format ELF:hexdump -s 5 -n 1 /bin/sh
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.