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

91

Je sais que certains processeurs sont Big Endian et que d'autres sont Little Endian. Mais existe-t-il une commande, un script bash, un script python ou une série de commandes pouvant être utilisées 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 déterminer quel processeur est utilisé par le système et d’y aller pour déterminer son endurance?

Jake Wilson
la source
Voici la solution en utilisant perl: stackoverflow.com/questions/2610849/...
SLU

Réponses:

110

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

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

0

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

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

1


La solution ci-dessus est astucieuse et fonctionne parfaitement pour Linux * 86 et Solaris Sparc.

J'avais besoin d'une solution shell uniquement (sans Perl) fonctionnant également sous AIX / Power et HPUX / Itanium. Malheureusement, les deux derniers ne sont pas agréables: AIX indique "6" et HPUX affiche une ligne vide.

En utilisant votre solution, j'ai pu concevoir quelque chose qui fonctionne sur tous ces systèmes Unix:

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

En ce qui concerne la solution Python publiée par une personne, cela ne fonctionne pas dans Jython car la machine virtuelle traite tout comme Big. Si quelqu'un peut le faire fonctionner dans Jython, postez-le!

En outre, j'ai trouvé cela, ce qui explique la finalité de diverses plates-formes. Certains matériels peuvent fonctionner dans l'un ou l'autre mode en fonction de la sélection du système d'exploitation: http://labs.hoffmanlabs.com/node/544


Si vous utilisez awk, cette ligne peut être simplifiée comme suit:

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

Pour les petites machines Linux qui n'ont pas 'od' (dites OpenWrt), essayez alors 'hexdump':

echo -n I | hexdump -o | awk '{ print substr($2,6,1); exit}'
Krissi
la source
2
Soit dit en passant, c'est une majuscule I(œil) plutôt qu'une minuscule l(ell).
Dennis Williamson
1
(Solaris) -> (Solaris, Sparc), bien que Sparc> = V9 soit bi-endian.
Cristian Ciupitu
1
Voulez-vous expliquer comment cela fonctionne?
Massimo
Cela ne semble pas fonctionner sur Android (Nexus 5). Je ne sais pas pourquoi ...
wjandrea
printf "\x1" | od -to2 | awk 'NR==1{print$2==1}'
Kaz
35

Si vous êtes sur une machine Linux assez récente (plus rien après 2012) puis lscpucontient maintenant ces informations:

$ lscpu | grep Endian
Byte Order:            Little Endian

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

Notez que je trouve cette réponse de cette réponse terrible sur Unix.SE . Cette réponse contient de nombreuses informations pertinentes, cet article n’en est qu’un résumé.

dotancohen
la source
31

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

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

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

ou tout simplement pour changer sys.exitde printpour une sortie imprimable

Mchurichi
la source
4
Cela ne fonctionnera pas sur les systèmes RHEL 5.x / CentOS 5.x qui exécutent Python 2.4.x. Voici une solution:python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
JPaget
10

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

À partir de la version 2.19 du paquet util-linux, la commande a été lscpulancée avec un champ relatif à Endianness. Alors maintenant, vous pouvez simplement utiliser cette commande pour le savoir:

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

Cela a été confirmé sur Ubuntu 12.10 et CentOS 6. Donc, je serais prêt à supposer que la plupart des noyaux Linux 3.0+ offrent maintenant cette fonctionnalité.

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

slm
la source
9

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"
Dennis Williamson
la source
4
Une doublure: python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))". Le code de sortie est 0 pour big endian et 1 pour little endian.
Cristian Ciupitu
7
python -c "import sys; print(sys.byteorder)"

Cela imprimerait la finesse du système.

prembhaskal
la source
6

Vous pouvez tirer parti 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 au format 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 octets) est 01, selon le format ELF , 01 est little endian et 02 est big endian.

Si vous n'en avez pas xxdsur votre box (et que vous avez une busybox), essayez ceci:

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

Tong Zhou
la source
Je pense que vous entendez par exemple un ELF arbitraire ... Puisqu'il existe d'autres types d'exécutables, notamment les scripts shell, perl, python, etc. il est intéressant de noter que le code se trouve dans le segment de texte, d'où l'erreur de l'ancien fichier texte occupé)
Pryftan
1
@Pryftan Merci de l'avoir signalé. Corrigé le!
Tong Zhou
@TongZhou Bienvenue; Heureux d'avoir pu aider!
Pryftan
Impressionnant! Première méthode à utiliser pour les systèmes d'exploitation intégrés basés sur busybox.
ogurets
3

J'ai trouvé un moyen de le faire avec Jython. Étant donné que Jython (Python sur la machine virtuelle Java) s’exécute sur une machine virtuelle, il génère toujours un rapport big endian, quel que soit le matériel.

Cette solution fonctionne pour Linux, Solaris, AIX et HPUX. Je n'ai pas testé sous Windows:

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

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

fae
la source
Edit: -n 1, désolé;)
fae
1
C'est exactement la même méthode qu'une réponse précédente , qui fournissait également plus de détails que la vôtre.
Kasperd
0

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

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

Une solution possible est la suivante. Nous générons un fichier appelé conftest.cqui 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 pour conftest.outiliser:

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

Ensuite nous courons:

$ strings conftest.o
PSILXINUEROCMIWD

Si la chaîne PSILXINUEROCMIWDse produit, la cible est little-endian. Si la chaîne LISPUNIXCOREDWIMse produit, c'est big-endian. Si aucune des deux chaînes ne se produit ou, ce qui est encore plus étonnant, les deux le sont, le test a échoué.

Cette approche fonctionne parce que les constantes "quatre cc" calculées dans le programme ont des valeurs indépendantes de la machine, indiquant les mêmes entiers, quelle que soit leur finalité. Leur représentation de stockage dans le fichier objet suit l’endianité du système cible, ce qui est visible via la vue basée sur les caractères située 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 recherchée n'est pas incorporée dans une autre chaîne, ce qui signifie qu'elle la stringsrestituera sur une ligne seule.

PS: la USPELLmacro ne met pas entre parenthèses les insertions d'arguments, car elles ont été conçues pour cet usage spécifique, et non pour être réutilisées.

Kaz
la source
Non pas que cela soit nécessaire pour tous les projets mais autoconf / automake n’a-t-il pas cette vérification? Mes projets sont toujours suffisamment petits pour pouvoir créer mes propres Makefiles (bien que pas toujours basiques). Je ne connais donc pas vraiment ces outils, à part quelques modifications si nécessaire et l'interface générale ... mais je me demande s'ils sont détectés. Peut-être que vous n'en aviez pas besoin même si c'était le cas, pensant simplement que je rejetterais cette possibilité.
Pryftan