链接程序和库指南

共享库依赖项

当运行时链接程序为某一程序创建内存段时,依赖项会说明提供该程序的服务时所需的共享库。通过重复连接引用的共享库及其依赖项,运行时链接程序可生成完整的进程映像。


注 –

即使在依赖项列表中多次引用了某个共享库,运行时链接程序也只会将该目标文件连接到进程一次。


查找共享库依赖项

链接动态可执行文件时,会显式引用一个或多个共享库。这些目标文件作为依赖项记录在动态可执行文件中。

运行时链接程序将使用此依赖项信息来查找并装入关联目标文件。这些依赖项的处理顺序与可执行文件的链接编辑期间对依赖项的引用顺序相同。

装入所有动态可执行文件的依赖项之后,将按依赖项的装入顺序检查每个依赖项,以找出其他依赖项。此过程会一直继续,直至找到并装入所有依赖项。此方法将导致所有依赖项按广度优先顺序排序。

运行时链接程序搜索的目录

运行时链接程序在两个缺省位置中查找依赖项。在处理 32 位目标文件时,缺省位置为 /lib/usr/lib。在处理 64 位目标文件时,缺省位置为 /lib/64/usr/lib/64。指定为简单文件名的任何依赖项都使用这些缺省目录名称作为前缀。生成的路径名用于查找实际文件。

使用 ldd(1) 可以显示动态可执行文件或共享库的依赖项。例如,文件 /usr/bin/cat 具有下列依赖项:


$ ldd /usr/bin/cat

        libc.so.1 =>     /lib/libc.so.1

        libm.so.2 =>     /lib/libm.so.2

文件 /usr/bin/cat 具有依赖项文件libc.so.1libm.so.2,即需要文件 libc.so.1libm.so.2

可以使用 dump(1) 检查目标文件中记录的依赖项。使用此命令可以显示文件的 .dynamic 节,并查找具有 NEEDED 标记的项。在以下示例中,前面的 ldd(1) 示例中显示的依赖项 libm.so.2 没有记录在文件 /usr/bin/cat 中。ldd(1) 显示了指定文件的全部依赖项,而 libm.so.2 实际上是 /lib/libc.so.1 的依赖项。


$ dump -Lvp /usr/bin/cat

 

/usr/bin/cat:

[INDEX] Tag      Value

[1]     NEEDED   libc.so.1

.........

在前面的 dump(1) 示例中,依赖项表示为简单文件名。换言之,名称中没有 '/'。使用简单文件名要求运行时链接程序根据一组规则生成路径名。包含嵌入 '/' 的文件名均按原样使用。

记录简单文件名是记录依赖项的一种最灵活的标准机制。链接编辑器的 -h 选项记录依赖项中的简单名称。 请参见命名约定记录共享库名称

通常,依赖项分布在 /lib/usr/lib/lib/64/usr/lib/64 以外的目录中。如果动态可执行文件或共享库需要在其他目录中查找依赖项,则必须显式指示运行时链接程序搜索此目录。

通过在链接编辑目标文件过程中记录运行路径,可以基于每个目标文件指定其他搜索路径。有关记录此信息的详细信息,请参见运行时链接程序搜索的目录

使用 dump(1) 可以显示运行路径记录。请参考包含 RUNPATH 标记的 .dynamic 项。在以下示例中,prog 具有依赖项 libfoo.so.1。运行时链接程序必须先搜索目录 /home/me/lib/home/you/lib,然后在缺省位置中查找。


$ dump -Lvp prog

 

prog:

[INDEX] Tag      Value

[1]     NEEDED   libfoo.so.1

[2]     NEEDED   libc.so.1

[3]     RUNPATH  /home/me/lib:/home/you/lib

.........

添加运行时链接程序搜索路径的另一种方法是设置环境变量 LD_LIBRARY_PATH。可以将该环境变量(在进程启动时即时对其分析)设置为一组以冒号分隔的目录。运行时链接程序会先搜索这些目录,然后搜索指定的任何运行路径或缺省目录。

这些环境变量非常适合在调试时使用,如将应用程序强制绑定到局部依赖项。在以下示例中,前面示例中的文件 prog 将绑定到当前工作目录中的 libfoo.so.1


$ LD_LIBRARY_PATH=. prog

尽管 LD_LIBRARY_PATH 作为一种影响运行时链接程序搜索路径的临时机制很有用,但强烈建议不要在生产软件中使用它。可引用此环境变量的所有动态可执行文件都将扩充其搜索路径。此扩充可能导致性能整体下降。另外,根据使用环境变量运行时链接程序搜索的目录中的说明,LD_LIBRARY_PATH 还会影响链接编辑器。

环境搜索路径可能导致 64 位可执行文件搜索包含与要查找的名称匹配的 32 位库的路径,反之亦然。运行时链接程序会拒绝不匹配的 32 位库,并继续搜索有效的 64 位匹配项。如果未找到匹配项,则会生成一条错误消息。通过将 LD_DEBUG 环境变量设置为包含 files 标记,可以详细观察此拒绝。 请参见调试库


$ LD_LIBRARY_PATH=/lib/64 LD_DEBUG=files /usr/bin/ls

...

00283: file=libc.so.1;  needed by /usr/bin/ls

00283: 

00283: file=/lib/64/libc.so.1  rejected: ELF class mismatch: 32–bit/64–bit

00283: 

00283: file=/lib/libc.so.1  [ ELF ]; generating link map

00283:     dynamic:  0xef631180  base:  0xef580000  size:      0xb8000

00283:     entry:    0xef5a1240  phdr:  0xef580034  phnum:           3

00283:      lmid:           0x0

00283: 

00283: file=/lib/libc.so.1;  analyzing  [ RTLD_GLOBAL  RTLD_LAZY ]

...

如果无法找到依赖项,则 ldd(1) 会指示找不到该目标文件。如果尝试执行应用程序,则会导致运行时链接程序生成相应的错误消息:


$ ldd prog

        libfoo.so.1 =>   (file not found)

        libc.so.1 =>     /lib/libc.so.1

        libm.so.2 =>     /lib/libm.so.2

$ prog

ld.so.1: prog: fatal: libfoo.so.1: open failed: No such file or directory

配置缺省搜索路径

对于 32 位应用程序,运行时链接程序使用的缺省搜索路径为 /lib/usr/lib。对于 64 位应用程序,缺省搜索路径为 /lib/64/usr/lib/64。使用 crle(1) 实用程序创建的运行时配置文件,可以管理这些搜索路径。在为生成时未使用适当 运行路径的应用程序建立搜索路径时,此文件通常很有用。

对于 32 位应用程序,可在缺省位置 /var/ld/ld.config 构造配置文件;对于 64 位应用程序,则可在缺省位置 /var/ld/64/ld.config 构造配置文件。此文件影响系统中各自类型的所有应用程序。此外,也可在其他位置创建配置文件,并且可使用运行时链接程序的 LD_CONFIG 环境变量选择这些文件。在缺省位置安装配置文件之前测试该文件时,后一种方法会很有用。

动态字符串标记

运行时链接程序允许扩展各种动态字符串标记。这些标记适用于过滤器、运行路径和依赖项定义。