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


91

我知道某些处理器是Big Endian,其他处理器是Little Endian。但是,是否可以在命令行上使用命令,bash脚本,python脚本或一系列命令来确定系统是Big Endian还是Little Endian?就像是:

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

还是仅仅确定系统使用的处理器并与其一起确定其Endianess是否更简单?


这里的解决方案用perl:stackoverflow.com/questions/2610849/...
SLU

Answers:


110

在大字节序系统上(SPARC上的Solaris)

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

0

在小端系统上(Linux在x86上)

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

1个


上面的解决方案很聪明,非常适合Linux * 86和Solaris Sparc。

我需要一个仅可用于外壳程序(无Perl)的解决方案,该解决方案也可在AIX / Power和HPUX / Itanium上使用。不幸的是,最后两个效果不佳:AIX报告“ 6”,而HPUX空行。

使用您的解决方案,我能够制作出在所有这些Unix系统上都可以使用的工具:

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

关于某人发布的Python解决方案,它在Jython中不起作用,因为JVM将所有内容都视为Big。如果有人可以在Jython工作,请发布!

另外,我发现了这一点,这解释了各种平台的字节顺序。根据操作系统选择的内容,某些硬件可以在任何一种模式下运行: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}'

2
顺便说一下,那是大写字母I(眼睛),而不是小写字母l(ell)。
丹尼斯·威廉姆森

1
(Solaris)->(Solaris,Sparc),尽管Sparc> = V9是双向的。
Cristian Ciupitu

1
关心解释它是如何工作的吗?
Massimo

这似乎在Android(Nexus 5)上不起作用。不知道为什么...
wjandrea

printf "\x1" | od -to2 | awk 'NR==1{print$2==1}'
卡兹(Kaz)

35

如果您使用的是较新的Linux机器(2012年之后的大多数机器),lscpu现在包含以下信息:

$ lscpu | grep Endian
Byte Order:            Little Endian

它已添加到lscpu2.19版本中,该版本位于Fedora> = 17,CentOS> = 6.0,Ubuntu> = 12.04中。

请注意,我在Unix.SE上的出色答案中找到了这个答案。该答案有很多相关信息,本文仅是其摘要。


31

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

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

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

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


4
这在运行Python 2.4.x的RHEL 5.x / CentOS 5.x系统上不起作用。解决方法:python -c "import sys;sys.exit(int(sys.byteorder!='big'))"
JPaget

10

主要答案可以使用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内核现在都提供了这一功能。

在Debian / Ubuntu系统上,您也可以使用以下命令,不确定该命令何时可用:

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

参考文献


9

这个Python脚本应该适合您:

#!/usr/bin/env python
from struct import pack
if pack('@h', 1) == pack('<h', 1):
    print "Little Endian"
else:
    print "Big Endian"

4
一班轮:python -c "from struct import pack;import sys;sys.exit(int(pack('@h',1)==pack('<h',1)))"。退出代码对于大字节序为0,对于小字节序为1。
Cristian Ciupitu

7
python -c "import sys; print(sys.byteorder)"

它将打印系统的状态。


6

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

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为大字节序。

如果您xxd的包装盒上没有(并且确实有busybox),请尝试以下操作:

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


我认为您的意思是任意ELF ...因为还有其他可执行文件类型,包括shell脚本,perl,python等。不是说您错了,而是-值得记住的是还有其他可执行文件类型(还有出于兴趣,代码位于文本段中,因此旧文本文件忙错误)。
Pryftan

1
@Pryftan感谢您指出这一点。更正了!
通州

@通州欢迎; 很高兴有帮助!
Pryftan

太棒了!适用于基于busybox的嵌入式OS的第一种方法。
ogurets '18

3

我在Jython找到了一种方法。由于Jython(JVM上的Python)在VM上运行,因此无论硬件如何,它始终报告大字节序。

该解决方案适用于Linux,Solaris,AIX和HPUX。尚未在Windows上测试:

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


0

要求略有不同:我需要在程序构建配置脚本中进行类似的测试,以确定编译目标计算机是位字节序还是低位字节序,而无需执行代码。脚本必须存放#define HAVE_LITTLE_ENDIAN 1config.h标题中,否则#define HAVE_LITTLE_ENDIAN 0

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

一个可能的解决方案是这个。我们生成一个名为的文件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

如果出现字符串PSILXINUEROCMIWD,则目标为小尾数。如果出现字符串LISPUNIXCOREDWIM,则为big-endian。如果两个字符串都没有出现,或者甚至更惊人地都没有出现,则说明测试失败。

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

两个零防护字确保字符串被隔离。这不是严格必要的,但可以确保我们要查找的字符串未嵌入其他字符串中,这意味着strings将其单独输出到一行中。

PS USPELL宏不会括号内的参数插入,因为它是为特定目的而不是重复使用而设计的。


并非所有项目都必须这样做,但是autoconf / automake是否没有此检查?我的项目总是足够小,可以在其中创建自己的Makefile(尽管并不总是基本的),所以我除了在必要时进行一些修改和常规界面之外,对其他工具一无所知。但是我确实想知道它们是否具有检测功能。也许即使您不需要它,也只是以为我会排除这种可能性。
Pryftan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.