应用程序在运行时如何解决不同版本的共享库?

42

我对Linux上的共享库如何工作还不太了解。我试图理解应用程序在运行时如何解析同一共享库的不同版本。

据我所知,一个共享库有三个“名称”,例如:

  1. libmy.so.1.2(真实名称,即实际的obj文件)
  2. libmy.so.1(SONAME,在实际的obj文件中嵌入)
  3. libmy.so(链接器名称,在链接时提供给链接器并嵌入可执行文件中)

当你通过LDCONFIG安装库时,它会创建以下符号链接:

  • (2) => (1)
  • (3) => (2)

现在假设我使用以下真实名称编译同一库的另一个版本,libmy.so.2.0。根据指南,SONAME应为libmy.so.2.0。

在应用程序链接时,我将使用哪个链接器名称作为“-l”标志?根据我阅读的指南(http://www.dwheeler.com/program-library/Program-Library-HOWTO/x36.htm),难道不应该是libmy.so吗?如果是这样,两个obj文件的版本将如何区分?

4个回答

49

当您创建共享对象时,您需要为其指定一个实际名称和一个SONAME(共享对象名称)。这些用于安装共享对象(它会同时创建对象和各种链接)。

因此,您可能会遇到以下情况:

pax> ls -al xyz*
lrwxrwxrwx  1 pax pax      0  Nov 18 2009  xyz.so -> xyz.so.1
lrwxrwxrwx  1 pax pax      0  Nov 18 2009  xyz.so.1 -> xyz.so.1.5
-rw-r--r--  1 pax pax  12345  Nov 18 2009  xyz.so.1.5

具有 xyz.so.1.5SONAMExyz.so.1

当链接器与 xyz.so 进行链接时,它会一直跟随文件链接到 xyz.so.1.5 并使用其 SONAMExyz.so.1 存储在生成的可执行文件中,以便在运行时进行绑定。

然后,当您运行可执行文件时,它尝试使用存储在可执行文件中的 SONAME,即 xyz.so.1,这将指向特定的 xyz.so.1.N(目前为 1.5,但可能会在以后更改为 1.6 .. 1.N)。

因此,您可以安装 xyz.so.1.6 并更新 xyz.so.1 链接以指向它,已链接的可执行文件将使用它(在运行时)。

这种多层方法的优点在于,您可以拥有同名的多个潜在不兼容库(xyz.so.1.*xyz.so.2.*),但是在每个主要版本中,您可以自由升级它们,因为它们应该是兼容的。
当您链接以创建新的可执行文件时:
- 那些链接到 xyz.so 的将获得最新主版本的最新次要版本。 - 其他链接到 xyz.so.1 的将获得特定主版本的最新次要版本。 - 仍然其他链接到 xyz.so.1.2 的将获得特定主版本的特定次要版本。
现在请记住上面那段话,我们来看看您的评论:
假设我编译了另一个版本的相同库,并使用以下实际名称:libmy.so.2.0。按照指南,SONAME 将是 libmy.so.2.0
不,我不这样认为。更有可能是libmy.so.2SONAME,这样你就可以对2.x流进行小的更新并获得最新的行为。

6
你抓住了我正在回答的中间环节。现在我只能补充说,如果 OP 感到好奇,他可以像这样使用 readelf -Wa /usr/lib/libstdc++.so.6 | grep SONAME 来检查系统上预安装库的 sonames,并看看指南如何得到贯彻实施。 - P Shved
是的,那是我的编辑错误,我真正想说的是“libmy.so.2”。因此,如果我正确遵循这三个要点,在链接到旧的主版本时,我只需指定相应的SONAME即可。我必须说,很多这些辅助文档在这方面都是误导性的。它们总是只讨论链接到最新主版本的部分,而没有明确限定这一事实。 - nisah
你能提供答案中信息的参考资料吗? - Piotr Dobrogost

2

在应用程序链接时,如果您指定-lmy,链接器将搜索名为libmy.so的文件。它会找到这个文件,并将您的可执行文件与其链接。如果此文件是符号链接,则您的应用程序将与符号链接的目标链接。

应用程序链接时间是确定使用哪个版本的动态库与您的应用程序链接的唯一位置。


0

@paxdiablo的第一条回答的补充:

ldconfig不会设置链接器名称;通常在库安装期间完成此操作,并且链接器名称只是作为符号链接创建为“最新”的soname或最新的实际名称。

这意味着xxx.so将链接到最新主版本动态库文件的最新次要版本。

我认为这解释了为什么:

  • 那些链接xyz.so的人将获得最新主版本的最新次要版本。

但我不知道安装如何设置链接器名称以及哪个工具进行设置(apt-get?)


-1
  1. 库在名称上有不同的版本。
  2. 名称为“lib”的软件包仅包含库,并且名称中有不同的版本。
  3. 系统将仅使用最新的库进行编译,除非您定义了其他库。
  4. 应用程序仅使用其需要的那些库。请检查ldd、readelf。
  5. 应用程序包含一个链接.so和.pc文件,请检查rpm系统以获取更多信息。 https://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging#Devel_Packages

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接