3

我想将我的程序作为二进制文件分发,而不是源代码形式。我有两个测试系统:一个较旧的 Linux(带有 glibc 2.10 的 openSUSE 11.2)和一个最近的(带有 glibc 2.15 的 LinuxMint 13)。现在,当我在 LinuxMint 系统上使用 glibc 2.15 编译我的程序,然后尝试在 openSUSE 系统上使用 glibc 2.10 启动二进制文件时,我收到以下两个错误:

./a.out: /lib/libc.so.6: version 'GLIBC_2.15' not found (required by ./a.out)
./a.out: /lib/libc.so.6: version 'GLIBC_2.11' not found (required by ./a.out)

这里让我感到困惑的是:为什么我也会在这里收到“glibc 2.11 not found”错误?我希望该程序现在需要 glibc 2.15,因为它是使用 glibc 2.15 编译的。为什么程序也在寻找 glibc 2.11?这是否意味着我的程序将在两个 glibc 版本(即 2.15 和 2.11)上运行?所以它至少需要2.11?还是无论如何都需要2.15?

另一个问题:glibc 向上兼容但不向下兼容的假设是否正确?例如,使用 glibc 2.10 编译的程序是否可以保证与任何未来版本的 glibc 完美配合?如果是这种情况,如果将来更改 PATH_MAX 之类的常量会怎样?目前它设置为 4096,我正在使用 PATH_MAX 常量为 realpath() POSIX 函数分配缓冲区。现在如果将来这个常数提高到 8192,可能会出现问题,因为我的程序只分配了 4096 个字节。还是我在这里误解了什么?

感谢您的解释!

4

1 回答 1

7

Libc 使用符号版本控制。这是相当高级的魔法,但基本上每个符号都根据它出现的版本附加标签。如果它的语义发生变化,则有两个版本,一个是旧语义,它是第一次出现的版本,另一个是新语义和它出现的版本。加载程序只会抱怨您的程序实际请求的符号。其中一些恰好是在 2.15 中引入的,而其中一些恰好是在 2.11 中引入的。

这样做的重点是保持 glibc 向后兼容。这真的很重要,因为有很多打包的软件,所有这些都是动态链接的,重新编译所有这些需要很长时间。还有很多软件没有可用的源代码,旧版本的 libc 可能不适用于新内核或其他新内核。

所以是的,glibc 是向后兼容的。只需确保针对需要运行它的最旧版本进行编译,因为它不(也不能)向前兼容。

Ad PATH_MAX:如果进行了这样的更改,glibc 将简单地导出使用新值的新版本符号和具有适当安全保证的旧版本符号,以使用针对旧值编译的代码。这就是所有魔法的要点。

于 2012-10-01T15:01:56.483 回答