【问题标题】:Understanding glibc了解 glibc
【发布时间】:2012-09-22 10:37:44
【问题描述】:

我想以二进制文件的形式分发我的程序,而不是源代码形式。我有两个测试系统:一个较旧的 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 个字节。还是我在这里误会了什么?

感谢您的解释!

【问题讨论】:

  • 尝试静态链接您的代码:gcc -static mycode.c ...
  • 另外:你的问题太多了。如果您只发布一个明确的问题,您将获得更好的答案。
  • @DouglasB.Staple:如果你这样做,你必须分发资源!!!
  • @DouglasB.Staple:这不是一个选项,因为那样我的程序将属于 GPL。

标签: c linux gcc glibc shared-libraries


【解决方案1】:

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

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

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

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

【讨论】:

  • 谢谢!有什么方法可以找出它引用的 2.15 的哪些符号?我真的很想知道这一点,因为我只是使用普通的旧 C 函数。真的无法想象为什么它需要 2.15 中的符号......
  • @Andreas:我相信lddobjdump 之一会列出所需的符号,包括它们的版本。
  • @Andreas:某些功能可能在 2.10 和 2.15 之间更改。也许是一些常数,一些结构的定义或其他东西。因此,该函数虽然源代码兼容,但将具有不同的二进制接口。提供了旧版本和新版本,但在编译时您总是会得到最新的定义。
  • @JanHudec:“是的,glibc 是向后兼容的” - 有官方参考资料吗?不幸的是,我找不到这些...
  • @andreee,我相信它在版本控制中有所暗示。只要主要的 so-version 没有改变,任何共享库都应该是向后兼容的。自 ELF 过渡以来,libc 一直是 libc.so.6。
猜你喜欢
  • 2016-12-03
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 2018-09-12
  • 2019-11-08
  • 2016-02-20
  • 1970-01-01
  • 2019-06-19
相关资源
最近更新 更多