在什么范围的机器上的二进制兼容性?

Ass*_*ins 5 c compiler-construction ubuntu shared-libraries

我在C中编写了一个简单的程序,并在Ubuntu上使用GCC编译它.这个文件会在另一台机器上运行吗?

  • 输出二进制文件的内容及其外部依赖项是什么?
  • 它可以在其他Linux发行版上运行,在什么情况下运行?
  • 它可以在其他操作系统上运行吗?

Nic*_*son 11

二进制不兼容有几个级别/来源.

首先,解决库不兼容问题

通常,如果你在另一台机器上运行二进制文件,使用不同版本的"相同操作系统"(无论这意味着什么......),那么它将运行正常.完全.问题不在于代码不起作用,而在于缺少代码:二进制文件所依赖的操作系统的位在目标计算机上不存在.找到要运行的代码是错误的,而不是运行代码(这样就完全没问题,直到尝试使用丢失的位!)

所以,你的Ubuntu gcc中的二进制文件最有可能运行在任何不比它编译的机器上的旧系统上.它取决于二进制文件从OS和系统库中确切依赖的功能.

很少有二进制文件没有外部依赖项.使用ldd输出检查依赖项.最容易引起问题的是libgcc依赖.libc和朋友很少改变,因此几乎不会导致兼容性方面的困难.GCC经常更改,因此会限制二进制文件运行的目标计算机.

一般规则是:使用您想要运行的最早的发行版作为您的构建机器.因此,使用RHEL 2构建机器,您将能够在任何较旧的系统上运行二进制文件(除了一些例外).这是保持简单的通用指南.如果你需要跨很多发行版的二进制兼容性,静态链接到libstdc ++(如果你使用C++)是一个很好的选择.静态链接到libgcc是危险的,除非你真的知道你在做什么,否则不要尝试.

最后,请注意,在其他UNIX平台上,库兼容性要简单得多; 它只是linux这样的痛苦.在AIX 6(比方说)或SunOS 5.8或HP-UX 11.00上编译的任何内容或任何在所有后续版本中都没有问题的运行.环境足够均匀,他们可以在系统库中附带成堆的遗留文件,以保证旧版本中的每个符号都可以在最新版本上使用,具有相同的语义.

其次,跨操作系统二进制文件:操作系统之间的运行时差异

这只是机器代码,因此您可能认为二进制文件应该适用于其他操作系统.他们不会.系统调用的一个重要原因是:当您需要从内核调用某些东西时(这对于大多数非平凡的功能来说是必需的),您必须知道如何"与内核通信".也就是说,你做了一个系统调用并告诉操作系统,"做了42件事,你知道".

系统调用的数量取决于内核.所以,Solaris二进制文件可以从linux中运行,除了那个停止几乎所有工作的那个.

事实上,一些操作系统确实支持其他内核的系统调用.FreeBSD知道linux系统调用,当你告诉它"做42件事"时,它检查你ELF标题中的一个标志,如果ELF标记为linux,则对linux系统调用号执行相应的操作.整齐.(当然,你需要在linux libs中链接......但是,静态链接的linux二进制文件在FreeBSD中运行正常,没有外部.)

第三,加载时跨OS兼容性

二进制不是"只是二进制"; 它包含一大堆元数据,在内核运行之前由内核解释.大多数二进制文件是一大堆代码和数据,以及链接器信息.但是,即使是没有任何外部依赖关系的东西也必须由内核解析.

某些内核了解多种二进制格式,例如PE,ELF或a.out(已废弃).Linux二进制文件永远不会在Windows上运行,即使它们没有进行任何系统调用(这样的二进制文件不能干净地退出,但为了示例...).这是因为MS不打算在他们的内核中添加ELF支持:Windows无法读取描述如何加载和启动代码的包装器,因此其中的代码将无法运行:Windows不能不知道文件的哪些位是代码!