跳转到内容

Ict-创新/LPI/102.3

来自维基教科书,开放的世界,开放的书籍

102.3 管理共享库

[编辑 | 编辑源代码]

候选人应该能够确定可执行程序依赖的共享库,并在必要时安装它们。


关键知识领域

  • 识别共享库
  • 识别系统库的典型位置。
  • 加载共享库。

库是一组函数,程序可以使用这些函数来实现它们的功能。在构建(链接)程序时,这些库可以静态或动态链接到可执行文件。静态链接意味着最终程序将在其文件中包含库函数。(lib.a)动态链接意味着当程序执行时,所需的库将加载到 RAM 中(lib.so)。


在编写应用程序时,开发人员会使用现有的软件库来提供应用程序所需的 functionality。当最终应用程序被编译时,有两种选择可用。

  • 使用所有必需的库编译到应用程序中构建应用程序。这被称为将库静态链接到应用程序。这样做的好处是应用程序安装后不会出现依赖性问题,但缺点是二进制文件的大小会增加,因为库在每个静态链接库的应用程序中都重复。最负面的影响是,内核无法通过仅加载一次重复代码来优化内存。相反,每个应用程序都加载了相同的代码。
  • 在运行时动态链接所需的依赖项。动态链接的可执行文件比静态链接程序小得多,因为它们不包含它们所依赖的库代码。使用动态链接允许运行使用相同库的程序来共享该库的一个副本,而不是占用内存来存储重复的副本。由于库代码是独立的,因此 Linux 发行版的包管理系统可以独立于应用程序更新库代码。由于这些原因,如今大多数程序都使用动态链接。

为了在运行时查找应用程序所需的库,Linux 需要知道在哪里查找它们。默认情况下,Linux 在以下受信任位置查找库文件

  • /lib: - 主要由 /bin 程序使用。
  • /usr/lib - 主要由 /usr/bin 程序使用。

库文件的其他位置可以在 /etc/ld.so.conf 文件中指定。ld.so.conf 文件可以包含 /etc/ld.so.conf.d 目录下的所有文件,具体取决于您的发行版。列表 5 显示了 64 位 Fedora 12 系统上的 /etc/ld.so.conf 的内容。

/etc/ld.so.conf 的内容


$ cat /etc/ld.so.conf

include ld.so.conf.d/*.conf

$ ls /etc/ld.so.conf.d/*.conf

/etc/ld.so.conf.d/kernel-2.6.31.12-174.2.19.fc12.x86_64.conf

/etc/ld.so.conf.d/kernel-2.6.31.12-174.2.22.fc12.x86_64.conf

/etc/ld.so.conf.d/kernel-2.6.31.12-174.2.3.fc12.x86_64.conf

/etc/ld.so.conf.d/mysql-x86_64.conf

/etc/ld.so.conf.d/qt-x86_64.conf

/etc/ld.so.conf.d/tix-x86_64.conf

/etc/ld.so.conf.d/xulrunner-64.conf

为了优化库位置和加载,ldconfig 命令会解析 ld.so.conf 文件中的目录和受信任目录,以在 /etc/ld.so.cache 中创建一个快速缓存。

当应用程序启动时,动态加载器使用 ld.so.cache 中的缓存信息来定位文件。对 ld.so.conf 文件的任何更改都需要运行 ldconfig 命令来更新 /etc/ld.so.cache 文件。


ldd 命令

[编辑 | 编辑源代码]

如果您想了解应用程序是静态链接的,还是动态链接应用程序的依赖项是什么,您可以使用 ldd 命令。例如 ldd /usr/sbin/apache 显示以下内容


ldd /usr/sbin/apache2

linux-vdso.so.1 => (0x00007ffff85ff000)

libpcre.so.3 => /lib/libpcre.so.3 (0x00007feeaf2e4000)

libaprutil-1.so.0 => /usr/lib/libaprutil-1.so.0 (0x00007feeaf0c1000)

libapr-1.so.0 => /usr/lib/libapr-1.so.0 (0x00007feeaee8b000)

libpthread.so.0 => /lib/libpthread.so.0 (0x00007feeaec6e000)

libc.so.6 => /lib/libc.so.6 (0x00007feeae8eb000)

libuuid.so.1 => /lib/libuuid.so.1 (0x00007feeae6e5000)

librt.so.1 => /lib/librt.so.1 (0x00007feeae4dd000)

libcrypt.so.1 => /lib/libcrypt.so.1 (0x00007feeae2a4000)

libdl.so.2 => /lib/libdl.so.2 (0x00007feeae09f000)

libexpat.so.1 => /lib/libexpat.so.1 (0x00007feeade76000)

/lib64/ld-linux-x86-64.so.2 (0x00007feeaf7ab000)

这告诉我们 apache2 是动态链接的,并依赖于列出的库。如果缺少库,ldd 将使用“未找到”一词输出依赖项。这在排查依赖性问题时很有用。


LD_LIBRARY_PATH

有时您可能需要覆盖动态库的默认搜索路径。这可能是为了您从源代码安装的应用程序,为了测试最新版本的库,或者如果应用程序依赖于您已安装在机器上的旧版本的库。

要将库添加到搜索路径,您需要定义和导出 LD_LIBRARY_PATH 变量,如下所示


# export LD_LIBRARY_PATH=/usr/lib/:/opt/someapp/lib;

LD_LIBRARY_PATH 是一个冒号分隔的目录列表,在 ld.so.cache 中指定的系统目录之前搜索这些目录。这允许临时覆盖在 ld.so.cache 和受信任目录中定义的库。



使用的文件、术语和实用程序

  • ldd
  • ldconfig
  • /etc/ld.so.conf
  • LD_LIBRARY_PATH


上一章 | 下一章

华夏公益教科书