Solaris:.so 和 .so.1 文件之间有什么区别?

Solaris:.so 和 .so.1 文件之间有什么区别?

我正在尝试了解 Solaris 上的链接器如何/为何动态加载某些库文件。我使用 ldd 来查看此信息(使用 -s 开关查看链接器尝试了哪些路径)。例如,如果我运行“ldd /usr/local/bin/isql -s”,我会注意到搜索到的库之一名为“libodbc.so.1”。我注意到这与它在搜索过程中找到的名为“libodbc.so”的文件不匹配。因此,它最终解析为“libodbc.so.1.0.0”和“libodbc.so.1”之间存在符号链接的位置。我的问题是 - 此处“.1”的意义是什么?是为了表示版本号吗?为什么有些安装程序会创建这些符号链接,而其他安装程序则不会?

答案1

这一问题并不特定于 Solaris。

当您安装共享库(或提供共享库的软件)时,您会得到三个文件,它们看起来相似但用途不同。

  • libfoo.so.1.0.0œ 这是(常规)数据文件。它包含库本身。您可以拥有多个这样的文件,并具有不同的版本。在这个文件中,有一个ELF 字段称为 SONAME,设置为libfoo.so.1。在 Linux 上,运行objdump -p libfoo.so.1.0.0 | grep SONAME即可查看。
  • libfoo.solibfoo.so.1.0.0œ 这是针对 libfoo 编译软件时使用的符号链接。当您指定-lfoo给链接器时,它将准确查找libfoo.so。通常,libfoo.so永远不会是常规文件,它始终是指向要用于链接的 libfoo 版本的符号链接。在复杂的构建环境中,您可能有多个版本的库,您可以使用此符号链接来选择要链接的版本。
  • libfoo.so.1libfoo.so.1.0.0‒ 这也是一个符号链接,当您运行需要库的二进制文件时会使用它。还记得我提到的 SONAME 字段吗?当您将二进制文件链接到 libfoo 时,二进制文件将记录库的 SONAME 并在运行时使用它。

此设置允许您同时安装同一库的多个版本。不同的二进制文件可能需要不同版本的库,每个二进制文件都会找到正确的库版本。通常,当出现向后不兼容的 API 更改时,上游会更改库的 SONAME。所有旧二进制文件仍使用旧 API,而新链接的二进制文件则使用新 API。

一些打包项目,Debian 就是一个例子,使用不同的包名称针对库的不同版本。这允许您独立地安装和卸载共享库的每个版本。

有一些极端情况。例如,共享库之间的依赖关系可能导致同时引入两个版本。请考虑:

foo → libbar.so.1, libbaz.so.1
libbar.so.1 → libbaz.so.1

假设我们安装了新版本的 libbaz 并重新编译 foo。现在我们有:

foo → libbar.so.1, libbaz.so.2
libbar.so.1 → libbaz.so.1

在运行时,foo 将加载libbaz.so.2libbar.so.1,并且libbar.so.1将加载libbaz.so.1。发现问题了吗?两个版本的 libbaz 被同时加载。我不太确定内存中代码布局的确切后果是什么,但实际上这会导致崩溃。

答案2

是的,“.1”表示版本号。这样就可以同时拥有同一个库的多个版本,而最常见的版本有一个没有版本号的链接。

如果不需要区分不同的版本,则可以不存在版本后缀。

相关内容