当我做 ls -l/usr/lib 我看到了很多libs "sameName.so.*.*" 延期。

  1. 这些扩展的意义是什么?
  2. 为什么创建软链接?他们有什么用?

一个例子将有助于理解。

有帮助吗?

解决方案

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

懒惰链接(或较晚绑定)的优点是,可以更改可执行文件的组件,而无需实际链接这些可执行文件。这允许在第三方组件中进行错误修复,而不必运送新的可执行文件等。

缺点与优势完全相同。您的可执行文件可以发现它对基础库的假设已更改,这可能会引起各种问题。

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

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

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链接。


实际的实现细节可能会有所不同(我的答案是基于较早的Unixes,Linux似乎比仅遵循符号链接更聪明地进行版本操作)。 IBM Developerworks有一篇关于如何完成的文章 这里.

当您创建共享对象时,您既给它既有一个真实的名称又给它 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 拥有 SONAMExyz.so.1.

当链接器链接到 xyz.so, ,它遵循链接一直到 xyz.so.1.5 并使用它 SONAMExyz.so.1 存储在可执行文件中。然后,当你 可执行的,它试图加载 xyz.so.1 这将指出一个特定的 xyz.so.1.N (不一定是1.5版)。

所以你可以安装 xyz.so.1.6 并更新 xyz.so.1 链接指向它,并且已链接的可执行文件将使用它。

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

当您链接新的可执行文件时:

  • 那些与之链接的 xyz.so 将获得最新的最新主要版本的次要版本。
  • 其他与之链接的 xyz.so.1 将获得最新的特定主要版本的次要版本。
  • 还有其他与 xyz.so.1.2 将获得特定主要版本的特定次要版本。

其他提示

它是 共享库的版本控制方案. 。每个库都应有3个名称:

  1. 真正的名字: 实际库名称, libfoo.so.1.2.3
  2. “儿子”: 名称记录在可执行文件中,名称Dynamic Linker都在寻找, libfoo.so.1.2. 。该名称实际上是在二进制本身内写入的,并将在链接时间的可执行文件中记录。它通常是图书馆真实姓名(通常是最新版本)的符号链接。
  3. 链接器名称: 构建程序时,您给链接器的名称。通常链接到最新的儿子。

例子

说你有 libfoo 版本1安装: libfoo.so -> libfoo.so.1.0 -> libfoo.so.1.0.0. 。您构建程序 bar-lfoo. 。现在链接到 libfoo 并会加载 libfoo.so.1.0 在由于Soname的运行时。然后,您升级到一个修补但兼容的二进制 libfoo.so.1.0.1 通过更换真实的二进制。 bar 仍然链接到 libfoo.so.1.0 并且不需要重建。

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

  1. libfoo.so.1.0 -> libfoo.so.1.0.1
  2. libfoo.so -> libfoo.so.1.1 -> libfoo.so.1.1.0

注意链接器名称已更新为最新版本(这是与您安装的标题相对应的版本 /usr/include).

你构建 baz, ,它链接到 libfoo.so 和负载 libfoo.so.1.1 在运行时。不是那个 bar 仍然对抗 libfoo.so.1.0 并且不需要更新。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top