Wie kann man feststellen, ob ein Linux-System Big Endian oder Little Endian ist?

91

Ich weiß, dass bestimmte Prozessoren Big Endian und andere Little Endian sind. Aber gibt es einen Befehl, ein Bash-Skript, ein Python-Skript oder eine Reihe von Befehlen, die in der Befehlszeile verwendet werden können, um festzustellen, ob ein System Big Endian oder Little Endian ist? So etwas wie:

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

Oder ist es einfacher festzustellen, welchen Prozessor das System verwendet, und anhand dessen die Endianess zu bestimmen?

Jake Wilson
quelle
Hier ist die Lösung mit Perl: stackoverflow.com/questions/2610849/…
slu

Antworten:

110

Auf einem Big Endian-System (Solaris auf SPARC)

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

0

Auf einem kleinen Endian-System (Linux auf x86)

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

1


Die obige Lösung ist clever und funktioniert hervorragend für Linux * 86 und Solaris Sparc.

Ich brauchte eine reine Shell-Lösung (ohne Perl), die auch unter AIX / Power und HPUX / Itanium funktioniert. Leider spielen die letzten beiden nicht gut: AIX meldet "6" und HPUX gibt eine leere Zeile aus.

Mit Ihrer Lösung konnte ich etwas herstellen, das auf all diesen Unix-Systemen funktioniert:

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

In Bezug auf die Python-Lösung, die jemand veröffentlicht hat, funktioniert sie in Jython nicht, da die JVM alles als "Groß" behandelt. Wenn es jemand in Jython zum Laufen bringen kann, poste es bitte!

Außerdem habe ich dies gefunden, was die Endianze verschiedener Plattformen erklärt. Einige Hardware-Komponenten können in beiden Modi betrieben werden, abhängig von der Auswahl des Betriebssystems: http://labs.hoffmanlabs.com/node/544


Wenn Sie awk verwenden, kann diese Zeile vereinfacht werden:

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

Für kleine Linux-Boxen, die kein 'od' haben (sagen Sie OpenWrt), versuchen Sie 'hexdump':

echo -n I | hexdump -o | awk '{ print substr($2,6,1); exit}'
krissi
quelle
2
Das ist übrigens Ieher ein Großbuchstabe (Auge) als ein Kleinbuchstabe l(Ell).
Dennis Williamson
1
(Solaris) -> (Solaris, Sparc), obwohl Sparc> = V9 Bi-Endian ist.
Cristian Ciupitu
1
Möchten Sie erklären, wie es funktioniert?
Massimo
Dies scheint auf Android (Nexus 5) nicht zu funktionieren. Ich
weiß
printf "\x1" | od -to2 | awk 'NR==1{print$2==1}'
Kaz
35

Wenn Sie auf einen relativ neuen Linux - Rechner sind (fast alles nach 2012) dann lscpuenthält jetzt folgende Informationen:

$ lscpu | grep Endian
Byte Order:            Little Endian

Dies wurde lscpuin Version 2.19 hinzugefügt , die sich in Fedora> = 17, CentOS> = 6.0, Ubuntu> = 12.04 befindet.

Beachten Sie, dass ich diese Antwort von dieser großartigen Antwort auf Unix.SE gefunden habe . Diese Antwort enthält viele relevante Informationen. Dieser Beitrag ist nur eine Zusammenfassung.

dotancohen
quelle
31

Hier ist ein eleganteres einzeiliges Python-Skript

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

Exit-Code 0bedeutet "Big Endian" und 1"Little Endian"

oder wechseln Sie einfach sys.exitzu printfür eine druckbare Ausgabe

mchurichi
quelle
4
Dies funktioniert nicht auf RHEL 5.x / CentOS 5.x-Systemen, auf denen Python 2.4.x ausgeführt wird. Hier ist ein python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
Update
10

Die Hauptantwort kann leicht vereinfacht werden mit awk:

Auf einem Big Endian-System (Solaris, SPARC)

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

Auf einem Little Endian-System (Linux, Intel)

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

Neuere Linux-Kernel

Ab Version 2.19 des Pakets util-linux wurde der Befehl lscpumit einem Feld für Endianness gestartet. Jetzt können Sie einfach diesen Befehl verwenden, um dies herauszufinden:

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

Dies wurde unter Ubuntu 12.10 und CentOS 6 bestätigt. Daher würde ich davon ausgehen, dass die meisten Linux-Kernel ab Version 3.0 dies anbieten.

Auf Debian / Ubuntu-Systemen können Sie auch diesen Befehl verwenden, da Sie sich nicht sicher sind, wann er verfügbar wurde:

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

Verweise

slm
quelle
9

Dieses Python-Skript sollte für Sie funktionieren:

#!/usr/bin/env python
from struct import pack
if pack('@h', 1) == pack('<h', 1):
    print "Little Endian"
else:
    print "Big Endian"
Dennis Williamson
quelle
4
Motto: python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))". Der Exit-Code ist 0 für Big Endian und 1 für Little Endian.
Cristian Ciupitu
7
python -c "import sys; print(sys.byteorder)"

Es würde die Endianess des Systems drucken.

prembhaskal
quelle
6

Sie können das ELF-Dateiformat nutzen, um die Endianze Ihres Systems zu bestimmen. Drucken Sie beispielsweise die ersten sechs Bytes einer beliebigen ELF-Datei in hexadezimaler Schreibweise aus:

xxd -c 1 -l 6 /bin/ls

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

Wenn die letzte Zeile (das sechste Byte) gemäß ELF-Format 01 ist, ist 01 Little Endian und 02 Big Endian.

Wenn Sie keine xxdauf Ihrer Box haben (und über eine Busybox verfügen), versuchen Sie Folgendes:

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

Tong Zhou
quelle
Ich denke, Sie meinen eine beliebige ELF ... Da es andere ausführbare Typen gibt, einschließlich Shell - Skripte, Perl, Python usw. Das heißt aber nicht, dass Sie sich anders irren - nur, dass es wert ist, daran zu denken, dass es andere ausführbare Typen gibt (und Bei Interesse befindet sich der Code im Textsegment, daher der alte Textdateifehler.
Pryftan
1
@Pryftan Danke für den Hinweis. Korrigiert es!
Tong Zhou
@ TongZhou Willkommen; Ich bin froh, Ihnen helfen zu können!
Pryftan
Genial! Erste Methode für eingebettete Busybox-Betriebssysteme.
ogurets
3

Ich habe einen Weg gefunden, dies in Jython zu tun. Da Jython (Python auf der JVM) auf einer VM ausgeführt wird, meldet es unabhängig von der Hardware immer Big Endian.

Diese Lösung funktioniert unter Linux, Solaris, AIX und HPUX. Habe noch nicht unter Windows getestet:

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

Ein einzeiliger Befehl basierend auf dem ELF-Format:
hexdump -s 5 -n 1 /bin/sh

fae
quelle
Edit: -n 1, sorry;)
Fae
1
Dies ist genau die gleiche Methode wie bei einer vorherigen Antwort , die auch mehr Details lieferte als Ihre.
Kasperd
0

Etwas andere Anforderung: Ich benötige einen Test wie diesen in einem Programmbuild-Konfigurationsskript, um festzustellen, ob der Kompilierungszielcomputer Bit oder Little Endian ist, ohne Code auszuführen . Das Skript muss #define HAVE_LITTLE_ENDIAN 1in einem config.hHeader abgelegt werden , sonst #define HAVE_LITTLE_ENDIAN 0.

Die Kompilierungszielmaschine unterscheidet sich möglicherweise von der Buildmaschine, da es sich möglicherweise um eine Kreuzkompilierung handelt. Dies erklärt auch, warum der Test nicht versuchen darf, kompilierten Code auszuführen. Es steht außer Frage, ein kleines C-Programm mit einer printfAussage zu haben, die die Antwort ausspuckt.

Eine mögliche Lösung ist dies. Wir generieren eine Datei mit dem Namen conftest.c:

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

Nun kompilieren wir dies conftest.omit:

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

Dann laufen wir:

$ strings conftest.o
PSILXINUEROCMIWD

Wenn die Zeichenfolge PSILXINUEROCMIWDvorkommt, ist das Ziel Little Endian. Wenn die Zeichenfolge LISPUNIXCOREDWIMvorkommt, ist es Big-Endian. Wenn keine der beiden Zeichenfolgen vorkommt oder erstaunlicherweise beide, ist der Test fehlgeschlagen.

Dieser Ansatz funktioniert, weil die im Programm berechneten "fourcc" -Konstanten maschinenunabhängige Werte haben, die unabhängig von der Endianzahl dieselben Ganzzahlen bezeichnen. Ihre Speicherdarstellung in der Objektdatei folgt der Endianität des Zielsystems und ist über die zeichenbasierte Ansicht unter sichtbar strings.

Die zwei Null-Schutzwörter stellen sicher, dass die Zeichenfolge isoliert ist. Dies ist nicht unbedingt erforderlich, stellt jedoch sicher, dass die gesuchte Zeichenfolge nicht in eine andere Zeichenfolge eingebettet ist, sodass stringssie in einer eigenen Zeile ausgegeben wird.

PS: Das USPELLMakro setzt die Argumenteinfügungen nicht in Klammern, da es für diesen speziellen Zweck erstellt wurde und nicht für die Wiederverwendung.

Kaz
quelle
Nicht, dass es für alle Projekte notwendig ist, aber hat autoconf / automake diese Prüfung nicht? Meine Projekte sind immer so klein, dass ich meine eigenen Makefiles erstellen kann (wenn auch nicht immer grundlegend), sodass ich diese Tools nicht wirklich kenne, außer dass ich bei Bedarf einige Änderungen vornehme und die allgemeine Oberfläche. Aber ich frage mich, ob sie erkannt werden. Vielleicht hast du es nicht einmal gebraucht, dachte nur, ich würde die Möglichkeit ausschließen.
Pryftan