什么是* .so。*。* libs

时间:2010-09-15 05:20:33

标签: linux symlink libs

当我在ls -l/usr/lib时,我看到很多带有"sameName.so.*.*"扩展名的库。

  1. 这些扩展有什么意义?
  2. 为什么要创建软链接?他们有什么用?
  3. 一个例子将有助于理解。

2 个答案:

答案 0 :(得分:8)

这是用于版本共享对象文件的技巧。这是一种避免由于延迟链接而产生的可怕DLL地狱的方法。

延迟链接(或后期绑定)的优点是可以更改可执行文件的组件,而无需实际重新链接这些可执行文件。这允许在第三方组件中修复错误,而无需发送新的可执行文件等。

缺点与优点完全相同。您的可执行文件可以发现它对底层库所做的假设已被更改,这可能会导致各种问题。

共享对象的版本控制是避免这种情况的一种方法。另一个是共享对象,但这也有利有弊,我不会在这里进入。

举例来说,假设你有xyz.so的版本1。您有一个文件和指向该文件的符号链接:

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

现在,当您创建一个可执行文件exe1,并将其与xyz.so链接时,它将遵循符号链接,以便将xyz.so.1存储在可执行文件中,因为它需要它在运行时加载。

这样,当您升级共享库时:

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

您的原始可执行文件exe1仍然加载共享对象的第1版。

但是,您现在创建的任何可执行文件(例如exe2)都将与共享对象的版本2链接。


实际的实现细节可能会有所不同(我的答案基于早期的UNIX,而Linux似乎比仅仅遵循符号链接更智能地进行版本控制)。 IBM developerWorks有一篇很好的文章介绍了它是如何完成的here

创建共享对象时,会为其指定实名和soname。这些用于安装共享对象(它创建对象和链接到它)。

所以你最终可以了解情况:

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

xyz.so.1.5拥有SONAME的{​​{1}}。

当链接器在xyz.so.1中链接时,它会跟随链接一直到xyz.so并使用其xyz.so.1.5 SONAME来存储在可执行文件中。然后,当您运行可执行文件时,它会尝试加载xyz.so.1,这将指向特定的xyz.so.1(不一定是版本1.5)。

因此,您可以安装xyz.so.1.N并更新xyz.so.1.6链接以指向它,而已链接的可执行文件将使用该链接。

这种多层方法的一个优点是,您可以拥有多个可能不兼容的同名库(xyz.so.1xyz.so.1.*),但是,在每个主要版本中,您可以自由升级它们<因为它们应该是兼容的。

链接新的可执行文件时:

  • xyz.so.2.*链接的人将获得最新主要版本的最新版本。
  • xyz.so关联的其他人将获得特定主要版本的最新版本。
  • 还有一些与xyz.so.1相关联的人会获得特定主要版本的特定次要版本。

答案 1 :(得分:6)

这是一个versioning scheme for shared libraries。每个图书馆都应该有3个名字:

  1. 真实姓名:实际的图书馆名称libfoo.so.1.2.3
  2. “SONAME”:可执行文件中记录的名称,动态链接器名称为libfoo.so.1.2。该名称实际上是在库二进制文件本身内部编写的,并将在链接时记录在可执行文件中。它通常是库的真实姓名(通常是最新版本)的符号链接。
  3. 链接器名称:在构建程序时为链接器指定的名称。通常链接到最新的SONAME。
  4. 实施例

    假设您已安装libfoo版本1:libfoo.so - &gt; libfoo.so.1.0 - &gt; libfoo.so.1.0.0。您使用bar制作计划-lfoo。它现在链接到libfoo并且由于SONAME而在运行时加载libfoo.so.1.0。然后通过替换实际二进制文件升级到修补但二进制兼容的libfoo.so.1.0.1bar仍然链接到libfoo.so.1.0,无需重建。

    现在想象一下你想要构建一个利用libfoo v1.1中不兼容的更改的新程序baz。您安装了新版本,系统现在并行安装了两个版本:

    1. libfoo.so.1.0 - &gt; libfoo.so.1.0.1
    2. libfoo.so - &gt; libfoo.so.1.1 - &gt; libfoo.so.1.1.0
    3. 注意链接器名称已更新为最新版本(这是与您在/usr/include中安装的标头对应的版本。)

      您构建baz,它会链接到libfoo.so并在运行时加载libfoo.so.1.1。不是bar仍然针对libfoo.so.1.0运行,并且不需要更新。