Linux下共享链接库 (1)

来源:互联网 发布:网络水军群 编辑:程序博客网 时间:2024/05/29 17:05

 

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

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

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

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

 

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

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

 

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

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

 

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

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

 

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

 

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

但是FilesystemHierarchyStandard(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中指定。很多RedHat衍生的Linux发行版在该文件中并不包含目录/usr/local/lib

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

 

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

 

原创粉丝点击