如何判断Linux系统是大端还是小端?

我知道某些处理器是Big Endian,而其他的则是Little Endian。 但是有没有一个命令,bash脚本,python脚本或命令行可以用来确定系统是Big Endian还是Little Endian? 就像是:

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

或者,更简单地确定系统正在使用什么处理器,并用它来确定它的Endianess?

在大端系统(Solaris on SPARC)上

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

0

在一个小端系统上(x86上的Linux)

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

1


上述解决scheme非常巧妙,适用于Linux * 86和Solaris Sparc。

我需要一个也可以在AIX / Power和HPUX / Itanium上运行的shell(仅限于Perl)解决scheme。 不幸的是,最后两个不好玩:AIX报告“6”和HPUX提供了一个空行。

使用你的解决scheme,我能够在所有这些Unix系统上创build一些工作:

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

关于某人发布的Python解决scheme,Jython无法正常工作,因为JVM将所有内容视为Big。 如果任何人可以得到它在Jython的工作,请张贴!

另外,我发现这个,这解释了各种平台的sorting。 某些硬件可以在任何模式下运行,具体取决于O / Sselect的内容: http : //labs.hoffmanlabs.com/node/544


如果你打算使用awk这行可以简化为:

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

对于没有“od”的小型Linux机器(比如OpenWrt),请尝试“hexdump”:

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

这是一个更优雅的Python单行脚本

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

退出码0表示大端, 1表示小端

或者只是改变sys.exitprint一个可打印的输出

如果你在一台相当新的Linux机器上(大多数情况下在2012年之后),那么lscpu现在包含这个信息:

 $ lscpu | grep Endian Byte Order: Little Endian 

这被添加到版本2.19中的lscpu ,Fedora> = 17,CentOS> = 6.0,Ubuntu> = 12.04。

请注意,我从Unix.SE上的这个了不起的答案中find了这个答案。 这个答案有很多相关的信息,这个post只是它的一个总结。

主要答案可以用awk稍微简化awk

在Big Endian系统(Solaris,SPARC)上,

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

在Little Endian系统上(Linux,Intel)

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

较新的Linux内核

从util-linux软件包2.19版本开始, lscpu命令开始包含一个与Endianness相关的字段。 所以现在你可以简单地使用这个命令来找出这个问题:

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

这已经在Ubuntu 12.10和CentOS 6上得到了证实。所以我愿意假设大多数3.0+的Linux内核现在都提供这个function。

在Debian / Ubuntu系统上,你也可以使用这个命令,不知道它何时变得可用:

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

参考

  • 在Linux中是否有系统命令报告字节序?

这个Python脚本应该适合你:

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

这将打印系统的永久性。

我find了一种在Jython中实现的方法。 由于Jython(JVM上的Python)运行在虚拟机上,因此无论硬件如何,它总是会报告大端。

该解决scheme适用于Linux,Solaris,AIX和HPUX。 没有在Windows上testing过:

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

您可以利用ELF文件格式来确定您的系统的字节顺序。 例如,以hex打印任意可执行文件的前六个字节:

xxd -c 1 -l 6 /bin/ls

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

如果最后一行(六字节)是01,按照ELF格式 ,01是小端,02是大端。

基于ELF格式的单行命令:
hexdump -s 5 -n 1 /bin/sh

稍有不同的要求:我需要在程序构buildconfiguration脚本中这样的testing来确定编译目标机器是位还是小端, 而不执行代码 。 该脚本必须将#define HAVE_LITTLE_ENDIAN 1config.h头文件中,否则将#define HAVE_LITTLE_ENDIAN 0

编译目标机器可能与构build机器不同,因为我们可能是交叉编译,这也解释了为什么testing不能尝试运行任何编译代码。 有一个C程序用printf语句吐出答案是不可能的。

这是一个可能的解决scheme。 我们生成一个名为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 }; 

现在,我们使用下面的代码将它编译成conftest.o

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

然后我们运行:

 $ strings conftest.o PSILXINUEROCMIWD 

如果stringPSILXINUEROCMIWD发生,目标是小尾数。 如果stringLISPUNIXCOREDWIM发生,它是big-endian。 如果这两个string都不出现,或者更令人惊讶的是两者都行,那么testing失败了。

这种方法是有效的,因为在程序中计算的“fourcc”常量具有与机器无关的值,表示相同的整数而不pipe字节顺序。 它们在目标文件中的存储表示遵循目标系统的字节序,并且可以通过strings下的基于字符的视图来看到。

两个零保护字确保string被隔离。 这不是绝对必要的,但它确保我们正在查找的string不embedded其他string中,这意味着strings将自行输出它。

PS USPELLmacros不加括号插入参数,因为它是为了这个特定的目的,而不是为了重用。