链接程序和库指南

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

运行时链接程序在两个缺省位置中查找依赖项。在处理 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