为什么 Unix/Linux 系统不遍历目录直到找到所需的链接库版本?

dae*_*let 17 libraries dynamic-linking shared-library ld

我有一个名为“alpha”的二进制可执行文件,它需要一个链接库(libz.so.1.2.7),它位于 /home/username/myproduct/lib/libz.so.1.2.7

在通过执行以下命令生成二进制可执行文件之前,我将其导出到我的终端实例。

export LD_LIBRARY_PATH=/home/username/myproduct/lib/:$LD_LIBRARY_PATH
Run Code Online (Sandbox Code Playgroud)

现在,当我生成另一个需要相同库但版本不同的应用程序“bravo”时,即 (libz.so.1.2.8) 在 中可用 /lib/x86_64-linux-gnu/libz.so.1.2.8,系统抛出以下错误。

version `ZLIB_1.2.3.3' not found (required by /usr/lib/x86_64-linux-gnu/libxml2.so.2)
Run Code Online (Sandbox Code Playgroud)

如果我取消设置LD_LIBRARY_PATH,“bravo”启动正常。我了解上述行为是因为LD_LIBRARY_PATH/etc/ld.so.conf查找链接库时优先于定义的目录路径,因此发生了上述错误。我只是好奇,如果库的第一个实例是不同的版本,为什么 UNIX/LINUX 的开发人员没有设计操作系统根据层次结构搜索其他目录中的链接库。

简单地说,UNIX/LINUX 系统遍历一组目录,直到找到所需的库。但是为什么它在找到预期版本之前不做同样的事情,而不是接受库的第一个实例而不管其版本如何?

Ste*_*itt 28

但是为什么它在找到预期版本之前不做同样的事情,而不是接受库的第一个实例而不管其版本如何?

据它所知,它确实如此。zlib.so.1.2.7并且zlib.so.1.2.8两者都有一个 soname zlib.so.1,所以你的alphabravo二进制文件说他们需要zlib.so.1. 动态加载器加载它找到的第一个匹配库;它不知道 1.2.8 版提供了bravo需要的附加符号。(这就是为什么发行版煞费苦心地指定额外的依赖信息,例如zlib1g (>= 1.2.8)for bravo。)

您可能认为这应该很容易修复,但事实并非如此,尤其是因为二进制文件和库将它们需要的符号与它们需要的库分开列出,因此加载器无法检查给定的库是否提供了所有需要的符号需要从它。可以通过多种方式提供符号,在符号和提供它们的库之间引入链接可能会破坏现有的二进制文件。还有符号插入的额外乐趣使事情复杂化(并使对安全敏感的开发人员撕毁他们的头发)。

某些库提供最终存储在 中的版本信息.gnu.version_r,并带有指向提供库的链接,这在此处会有所帮助,但libz不是其中之一。

(考虑到 sonames,我希望你的alpha二进制文件可以正常工作zlib.so.1.2.8。)

  • @John 不,唯一的保证是具有相同 soname 的库是向后兼容的;较新的库可以添加功能,但不能以向后不兼容的方式删除或更改任何功能。也就是说,针对 zlib 1.2.7 构建的二进制文件将适用于那个或任何更新的 zlib 1;但是针对 zlib 1.2.8 构建的二进制文件不一定适用于较旧的 zlib 1。(语义版本控制允许这样做;但 soname 处理不是语义版本控制。) (4认同)
  • @John 是的,我怀疑我们达成了暴力协议,我误解了你的意思。`zlib` 无论如何都不使用 `libtool`,除了在达尔文它是 `ar` ;-)。 (2认同)