Linux下共享链接库 (1)

本文详细介绍了Linux环境下共享链接库的工作原理及管理方式,包括soname、realname和linker name的区别,以及ldconfig的作用和库的安装位置规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

共享链接库当应用程序启动时被加载。当一个共享链接库被成功安装后,所有的应用程序从此以后都会自动使用新的共享库。实际上它要比这个更灵活更复杂,因为 Linux 采用了如下方法允许你:

  1. 更新库但是仍然支持应用程序使用老的,不向后兼容的版本;

  2. 当执行应用程序时可以覆盖指定的库甚至是库中特定的函数;

  3. 就算应用程序正在运行并使用已经存在的库,仍然可以做以上的事情。

 

为了让共享链接库支持这些特性,我们必须遵循一些惯例和规范。首先你需要明白库的各种名字,特别是 soname real name 。你也必须知道这些库应该被放在文件系统中的什么地方。

每一个共享链接库都有一个特别的名字 soname soname 由前缀 lib ,库名,扩展名 .so ,然后是 . 和一个版本号组成。版本号会随着接口的变化而递增。最底层的 C 库是一个例外,因为它不是以 lib 打头。全限定的 soname 会以它所在的目录作为前缀。在一个运行的系统中全限定的 soname 只是 real name 的符号链接。

 

每个共享链接库都有一个 real name ,它是包含真正库代码文件的名字。 Real name 是由 soname 后跟一个 . ,次版本号,另一个 . ,和发布版本号组成。最后的 . 和发布版本号是可选的。次版本号和发布版本号支持配置控制,以此让你知道现在安装的库是什么版本。

另外,还有个名字用于编译器请求链接库,我们可以称之为 linker nam 。它只是 soname 去掉版本号。

 

管理动态链接库的关键就是区分这些名字。在应用程序中,当它们内部列出自己需要的共享链接库时,只要列出 soname 即可。恰恰相反,当你创建一个共享链接库时,你只需要创建一个给定名字的库即可 ( 可以附带更具体的版本信息 ) 。当安装库的一个新版本时,你把它安装在某个特定的文件夹然后运行程序 ldconfig Ldconfig 会检测已经存在的文件并创建 soname 符号连接到 real name ,同时也会建立缓存文件 /etc/ld.so.cache

Ldconfig 并不会建立 link name 。典型地这应该在库安装的时候完成, linker name 只是简单地作为最新的 soname 或者 real name 的符号链接。我本推荐 linker name 应该是 soname 的符号链接,因为在大多数场合如果你更新库,你总是希望在链接时自动使用它。我问过 H.J.Lu 为什么 ldconfig 不自动建立 linker name 。他的解释基本上是你可能想要使用最新的版本运行代码,但是要用老版本来开发。所以, ldconfig 不会假设你到底需要把应用程序链接到什么版本,所以,安装程序要明确修改符号链接来更新链接器用什么版本的库。

 

因此, /usr/lib/libreadline.so.3 是一个全限定的 soname ldconfig 会设置符号链接到某个 real name 比如 /usr/lib/libreadline.so.3.0 。也会有一个 linker name /usr/lib/libreadline.so ,一个指向 /usr/lib/libreadline.so.3 的符号链接。

 

共享链接库必须被放在文件系统的某个地方。大多数开源软件都倾向于遵循 GNU 标准。 GNU 标准推荐当发布源代码时把所有库默认安装在 /usr/local/lib 下,所有的命令安装在 /usr/local/bin 下。它也定义了一些关于如何覆盖这些默认设置和调用安装例程的约定。

但是 Filesystem Hierarchy Standard(FHS) 也讨论了应该在发布时将库安装在什么目录下。根据 FHS 规范,大部分库都应该安装在目录 /usr/lib ,但是启动时所需要的库必须在目录 /lib ,非系统库应该在目录 /usr/local/lib

 

这两份文档的规定并不冲突: GNU 规范推荐的默认目录是针对源代码的开发人员,而 FHS 推荐的默认目录是对发布者而言的。注意,如果你的库调用了一些程序,并且这些程序只能被库调用,那么你应该把这些程序放在 /usr/local/libexec 目录下 ( 对于发布时的 /usr/libexec 目录 )

 

GNU 基于 glibc 的系统中,包含所有的 Linux 操作系统,启动 ELF 二进制可执行文件都会导致程序加载器被自动加载并执行。在 Linux 下,加载器是 /lib/ld-linux.so.X(X 是版本好 ) 。它会依次找到并加载所有其他应用程序用到的共享链接库。

所以的搜索目录在文件 /ect/ld.so.conf 中指定。很多 Red Hat 衍生的 Linux 发行版在该文件中并不包含目录 /usr/local/lib

如果你只是想覆盖库中的一些方法,但是保持库的其他部分不变,你可以在文件 /etc/ld.so.preload 中输入该库的名字。这个方法典型用于紧急的 patch 。发行版在发布时通常不会包含这样的文件。

 

在程序启动时搜索所有的目录会很低效,所以缓存会被用到。 ldconfig 默认会读取文件 /etc/ld.so.conf ,建立合适的符号链接到动态链接目录,接着会写缓存到文件 /etc/ld.so.cache ,然后这些动态链接库就可以被其他程序调用了。这大大加速了访问链接库的时间。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值