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

时间:2012-09-09 11:49:19

标签: c ubuntu compiler-construction shared-libraries

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

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

2 个答案:

答案 0 :(得分:11)

二元不兼容有几个级别/来源。

首先,解决库不兼容问题

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

因此,来自你的Ubuntu gcc的二进制文件很可能运行在任何不比它编译的机器上的旧系统上。它取决于二进制文件从操作系统和系统库中确切依赖的功能。

很少有二进制文件没有外部依赖项。在输出中使用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中运行正常,没有外部。)

第三,加载时跨服务器兼容性

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

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

答案 1 :(得分:0)

a.out.o)文件适用于类Unix操作系统的计算机。 (@Nicholas Wilson上面给出的操作系统的详细信息)

.o包含.c文件中提到的所有库。从库中复制被调用函数的副本,并将其与.o文件中给出的代码一起制作成.c文件。

再次编译.o文件以获取可执行文件。

使用.o文件,如果您正在处理一个大型项目,其中每个部门都有自己的源文件(.c),并且需要生成一个可执行文件。您可以通过编译.c文件来获取它。编译后,您将获得.o个文件。现在,您可以将所有这些.o文件合并为一个可执行文件。

相关问题