学习 Linux,101: 管理共享库

来源:百度文库 编辑:神马文学网 时间:2024/05/01 17:16:43

学习 Linux,101: 管理共享库

找到并加载程序所需要的共享库

Ian Shields, 资深程序员, EMCIanShields 参与 developerWorks Linux 专区的许多 Linux 项目。他是 IBM 北卡罗来纳州 ResearchTriangle Park 的一名高级程序员。他于 1973 年作为一名系统工程师加入 IBM位于澳大利亚堪培拉的子公司。此后,在加拿大蒙特利尔和北卡罗来纳州 RTP 从事通信系统和普适计算。他拥有多项专利。他毕业于 AustralianNational University,本科学位是纯粹数学和哲学。他拥有北卡罗来纳州州立大学的计算机硕士和博士学位。
(An IBM developerWorks Contributing Author)

简介: 学习如何为 Linux 中可执行程序选择共享库以及如何加载共享库。您可以使用本文中的资料来学习,备考 Linux 系统管理员认证的 LPI 101 考试,当然也可以是出于爱好而学习。

查看本系列更多内容

标记本文!

发布日期: 2010 年 4 月 15 日
级别: 中级其他语言版本: 英文
访问情况 899 次浏览
建议: 0 (添加评论)

平均分 (共 8 个评分 )

关于本系列

本系列文章帮助您学习 Linux 系统管理任务相关知识。您可以使用本系列文章中的资料准备Linux Professional InstituteCertification 级别 1 (LPIC-1)考试 。

请参见我们的学习 Linux,101:LPIC-1 路线图,查看本系列中各文章的介绍和链接。该路线图目前仍然在更新中,目前反映的最新内容是 LPIC-1 考试的最新目标(2009 年 4 月)。在我们完成文章后,我们会将其添加到路线图中。但是,与此同时,您可以在我们的 LPI 认证考试准备教程 中找到类似资料的早期版本,这些内容支持 2009 年 4 月以前发布的 LPIC-1 目标。

概述

在本文中,学习如何找到并加载 Linux 可执行程序所需的共享库。您将学到:

  • 确定程序需要哪些共享库
  • 了解系统如何找到共享库
  • 加载共享库

本文将帮助您准备 Linux Professional Institute's Junior Level Administration (LPIC-1) 考试 101 中主题 102 下的目标 102.3。该目标的权值为 1。

先决条件

为了更有效利用这部分内容,您需要具有基本的 Linux 知识,并需要准备一个 Linux 系统,用于练习本文介绍的命令。有时候不同版本的程序输出格式不同,因此您所得到的结果未必总是与此处的相同。特别要指出,这里的很多例子来自 64 位系统。我们引入了很多来自 32 位系统的例子,来说明两者的显著差异 。


回页首

静态与动态链接

联系 Ian

Ian 是我们的一位最受欢迎、最高产的作者。查看 Ian 的个人信息,与 Ian、其他作者和 My developerWorks 的其他读者联系。

Linux 系统当中有两类可执行程序:

  • 静态链接 可执行程序包含了其所需的全部库函数;所有库函数都连接到程序中。 这类程序是完整的,其运行不需要外部库的支持。 静态链接程序的优点之一是其安装之前不需要做环境准备工作 。
  • 动态链接 可执行程序要小得多;这类程序运行时需要外部 共享 函数库的支持,因此好像并不完整。除了程序体小之外,动态链接允许程序包指定必须的库,而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库,这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因,当前多数程序采用动态链接技术。

在许多 Linux 系统中有个很有趣的例子,ln 命令(/bin/ln),用于在文件之间生成链接,不论是 链接还是 (或者 符号 )链接。 该命令使用共享库。共享库经常会引入库通用名与库特定层级之间的符号链接,所以如果因为某些原因链接没有出现或已断开,那么 ln命令本身就无法起作用,会发生循环错误。为避免此类问题,一些 Linux 系统包含了lnsln(/sbin/sln)之间的静态链接版本。清单 1 说明了采用动态链接的ln 与采用静态链接的sln之间大小的显著差别。该例子来自 Fedora 12 64-bit 系统。


清单 1. sln 与 ln 的大小

[ian@echidna ~]$ ls -l /sbin/sln /bin/ln
-rwxr-xr-x. 1 root root 47384 2010-01-12 09:35 /bin/ln
-rwxr-xr-x. 1 root root 603680 2010-01-04 09:07 /sbin/sln


回页首

需要哪些库?

尽管当前的 LPI 考试不涉及此类问题,但您还是应当明确当今很多 Linux 系统所运行的硬件同时支持 32 位及 64 位程序。很多库同时编译为 32 位及 64 位版本。64 位版本通常存放在文件系统的 /lib64 目录树中,而 32 位版本则位于 /lib 目录树中。您可能会在 64 位 Linux 系统中同时发现 /lib/libc-2.11.1.so 以及 /lib64/libc-2.11.1.so 。这两个库允许 32 位及 64 位 C 程序在 64 位 Linux 系统当中运行。

关于 ldd命令

除了明确静态链接程序比较大之外,如何确定程序是否为静态链接?如果是静态链接,如何知道它需要哪些库?ldd 命令能够回答这些问题。如果您正在运行 Debian 或 Ubuntu之类的程序,可能找不到 sln 命令,因此您可能会检查 /sbin/ldconfig 能否执行。清单 2 展示了ldd 命令关于 ln 以及 sln 执行情况,还有 ldconfig 可执行情况的输出。该例子来自 Fedora 12 64-bit 系统(echidna)。为了进行对比,还列出了来自旧版本 Fedora 8 32-bit 系统(pinguino)关于 /bin/ln 的输出 。


清单 2. ldd 关于 sln 以及 ln 的输出

[ian@echidna ~]$ #Fedora 12 64-bit
[ian@echidna ~]$ ldd /sbin/sln /sbin/ldconfig /bin/ln
/sbin/sln:
not a dynamic executable
/sbin/ldconfig:
not a dynamic executable
/bin/ln:
linux-vdso.so.1 => (0x00007fff644af000)
libc.so.6 => /lib64/libc.so.6 (0x00000037eb800000)
/lib64/ld-linux-x86-64.so.2 (0x00000037eb400000)

[ian@pinguino ~]$ # Fedora 8 32-bit
[ian@pinguino ~]$ ldd /bin/ln
linux-gate.so.1 => (0x00110000)
libc.so.6 => /lib/libc.so.6 (0x00a57000)
/lib/ld-linux.so.2 (0x00a38000)

因为 ldd 与动态链接有关,这告诉我们 sln 与 ldconfig 都是静态链接的,它们 “不是一个动态可执行文件”,同时告诉我们 ln 命令所需共享库的名字(linux-vdso.so.1、libc.so.6 和 /lib64/ld-linux-x86-64.so.2)。注意, .so 指明这些是 共享库 或者动态库。这一输出结果提供了您想了解的三类不同信息。

linux-vdso.so.1
是 Linux Virtual Dynamic Shared Object ,这一点我们稍后讨论。您还可以在 Fedora 8 中发现 linux-gate.so.1。
libc.so.6
具有指向 /lib64/libc.so.6. 的指针。
/lib64/ld-linux-x86-64.so.2
指向其他库的绝对路径。

在清单 3 中,通过 ls -l 命令,发现最后的两个库依次与库的特定版本之间具有符号链接。该例子来自 Fedora 12 64-bit系统 。


清单 3. 库符号链接

[ian@echidna ~]$ ls -l /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2
lrwxrwxrwx. 1 root root 12 2010-01-14 14:24 /lib64/ld-linux-x86-64.so.2 -> ld-2.11.1.so
lrwxrwxrwx. 1 root root 14 2010-01-14 14:24 /lib64/libc.so.6 -> libc-2.11.1.so

Linux Virtual Dynamic SharedObjects

在早期的 x86 处理器中,用户程序与管理服务之间的通信通过软中断实现。随着处理器速度的提高,这已成为一个严重的瓶颈。自 Pentium® II 处理器开始,Intel® 引入了 FastSystem Call 装置来提高系统调用速度,即采用 SYSENTER 和 SYSEXIT 指令,而不是中断。

您所看到的 linux-vdso.so.1 是个虚拟库,或者说是 Virtual Dynamic Shared Object ,它只存在于程序的地址空间当中。在旧版本系统中该库为 linux-gate.so.1。该虚拟库为用户程序以处理器可支持的最快的方式(对于特定处理器,采用中断方式;对于大多数最新的处理器,采用快速系统调用方式)访问系统函数提供了必要的逻辑 。


回页首

动态加载

通过前面的内容,您会很奇怪的发现/lib/ld-linux.so.2 以及它的 64 位版本,/lib64/ld-linux-x86-64.so.2,看上去都像是共享库,都在其各自的权限内可执行。它们是负责实现动态加载的代码。它们读取可执行程序的头信息,这些信息采用 Executable andLinking Format 或者( ELF )格式。它们通过这些消息,来确定哪些库是必须的,以及哪些库需要加载。然后执行动态链接,把可执行程序当中所有的地址指针与需要加载的库联系起来,这样程序就可以运行了。

有关 ld-linux.so 的帮助也描述了 ld.so,它为早期的 a.out 二进制格式提供类似的功能。清单 4 举例说明,如何利用 ld-linux.so 的 --list 选项来显示与清单 2 当中ln命令与 ldd 命令显示结果相同的内容。


清单 4. 利用 ld-linux.so 来展示库需求

[ian@echidna ~]$ /lib64/ld-linux-x86-64.so.2 --list /bin/ln
linux-vdso.so.1 => (0x00007fffc9fff000)
libc.so.6 => /lib64/libc.so.6 (0x00000037eb800000)
/lib64/ld-linux-x86-64.so.2 (0x00000037eb400000)

[ian@pinguino ~]$ /lib/ld-linux.so.2 --list /bin/ln
linux-gate.so.1 => (0x00110000)
libc.so.6 => /lib/libc.so.6 (0x00a57000)
/lib/ld-linux.so.2 (0x00a38000)

注意,两个清单中的十六进制地址有可能不同。在两次运行 ldd 命令时,该地址也可能不相同。


回页首

动态库配置

动态加载器怎样找到可执行程序?对于 Linux 当中的很多问题,都在 /etc 当中有相应的配置文件。事实上,有两个配置文件,/etc/ld/so/conf 以及 /etc/ld.so.cache。清单 5 展示了 Fedora 12 64 位系统当中 /etc/ld.so.conf 的内容。注意,/etc/ld.so.conf 文件指明所有来自 ld.so.conf.d 子目录的 .conf 文件都应当被包含。旧版系统中可能包含 /etc/ld/so/conf 的所有条目,而不包含 /etc/ld.so.conf.d 目录中的条目。您的系统当中 /etc/ld.so.conf 或者 /etc/ld.so.conf.d 目录的实际内容可能与此处有所差别。


清单 5. /etc/ld.so.conf 的内容

[ian@echidna ~]$ cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
[ian@echidna ~]$ 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 文件、所有 ld.so.conf.d 包含的文件、所有受信目录当中的库、/lib 和 /usr/lib,以及命令行当中所支持的其他内容 。ldconfig 命令在 /etc/ld.so.cache 中为最近使用过的共享库生成必须的链接和 cache 。动态加载器利用来自 ld.so.cache 的缓存文件来定位需要动态加载及链接的文件。如果改变了 ld.so.conf(或在 ld.so.conf.d 中增加新文件),必须运行 ldconfig 命令(以 root 用户身份)来重构 ld.so.cache 文件。

通常,可在不加参数的情况下,使用 ldconfig 命令来重构 ld.so.cache 文件。可以利用一些参数来改变这一使用习惯。一般情况下,可使用 man ldconfig 来获得更多信息。清单 6 举例说明利用参数 -p 来展示 ld.so.cache 的内容。


清单 6. 使用 ldconfig 来展示 ld.so.cache

[ian@lyrebird ian]$ /sbin/ldconfig -p | less
1602 libs found in cache `/etc/ld.so.cache'
libzip.so.1 (libc6,x86-64) => /usr/lib64/libzip.so.1
libz.so.1 (libc6,x86-64) => /lib64/libz.so.1
libz.so (libc6,x86-64) => /usr/lib64/libz.so
libx86.so.1 (libc6,x86-64) => /usr/lib64/libx86.so.1
libx11globalcomm.so.1 (libc6,x86-64) => /usr/lib64/libx11globalcomm.so.1
libxul.so (libc6,x86-64) => /usr/lib64/xulrunner-1.9.1/libxul.so
libxtables.so.2 (libc6,x86-64) => /usr/lib64/libxtables.so.2
libxslt.so.1 (libc6,x86-64) => /usr/lib64/libxslt.so.1
libxslt.so (libc6,x86-64) => /usr/lib64/libxslt.so
libxpcom.so (libc6,x86-64) => /usr/lib64/xulrunner-1.9.1/libxpcom.so
libxml2.so.2 (libc6,x86-64) => /usr/lib64/libxml2.so.2
libxml2.so (libc6,x86-64) => /usr/lib64/libxml2.so
...
libABRTdUtils.so.0 (libc6,x86-64) => /usr/lib64/libABRTdUtils.so.0
libABRTUtils.so.0 (libc6,x86-64) => /usr/lib64/libABRTUtils.so.0
ld-linux.so.2 (ELF) => /lib/ld-linux.so.2
ld-linux-x86-64.so.2 (libc6,x86-64) => /lib64/ld-linux-x86-64.so.2


回页首

加载指定的库

如果您正在运行需要特定旧版共享库支持的程序,或者您正在开发新的共享库或现有共享库的新版本,您可能希望覆盖加载器的默认搜索路径。使用安装在 /opt 树当中特定于产品共享库的脚本文件可能也需要这一功能。

就如同可通过设置变量 PATH 来为可执行程序指定搜索路径一样,可以将变量 LD_LIBRARY_PATH 设置为用冒号分割的,为加载 ld.so.cache 当中所指定的共享库需要搜索的目录清单。例如,可使用命令:

export LD_LIBRARY_PATH=/usr/lib/oldstuff:/opt/IBM/AgentController/lib

参见下面的 参考资料 来获得细节信息以及相关文章的链接。


参考资料

学习

  • 使用 学习 Linux,101:LPIC-1 路线图 找到可以帮助您准备基于 2009 年 4 月的目标的 LPIC-1 认证的 developerWorks 文章。

  • 在 LPIC Program 站点中,可以找到 Linux Professional Institute 的 Linux 系统管理认证的三个级别的具体目标、任务列表、样例问题。具体请参见 2009 年 4 月的 LPI 考试 101 和 LPI 考试 102 目标。请随时关注 LPIC Program 站点,以便了解最新目标。

  • 回顾 developerWorks 上的整个 LPI 考试准备系列,学习 Linux 基础知识,并为参加基于 2009 年 4 月之前的早期 LPI 考试目标的系统管理员认证考试准备。

  • Linux 文档项目 提供了大量有用的文档,特别是 HOWTO 文档。

  • 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更多参考资料,查阅我们 最受欢迎的文章和教程。

  • 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程。

  • 随时关注 developerWorks 技术活动和网络广播。

  • 观看 developerWorks 演示中心,包括面向初学者的产品安装和设置演示,以及为经验丰富的开发人员提供的高级功能。

获得产品和技术

  • 以最适合您的方式 IBM 产品评估试用版软件:下载产品试用版,在线试用产品, 在云环境下试用产品,或者在 IBM SOA Sandbox for People 中花费几个小时来学习如何高效实现 Service Oriented Architecture。

讨论

  • 参与论坛讨论。

  • 加入 My developerWorks 社区。查看开发人员参与的博客、论坛、组和 wikis,并与其他 developerWorks 用户交流。

关于作者

IanShields 参与 developerWorks Linux 专区的许多 Linux 项目。他是 IBM 北卡罗来纳州 ResearchTriangle Park 的一名高级程序员。他于 1973 年作为一名系统工程师加入 IBM位于澳大利亚堪培拉的子公司。此后,在加拿大蒙特利尔和北卡罗来纳州 RTP 从事通信系统和普适计算。他拥有多项专利。他毕业于 AustralianNational University,本科学位是纯粹数学和哲学。他拥有北卡罗来纳州州立大学的计算机硕士和博士学位。