Menu Close
Red Hat Training
A Red Hat training course is available for RHEL 8
第 4 章 使用 GCC 创建库
本章论述了创建库的步骤,并解释了 Linux 操作系统为库使用的必要概念。
4.1. 库命名惯例
库使用一个特殊的文件名惯例: 称为 foo 的库应该 作为文件 libfoo.so
或 libfoo.a
存在。本约定通过链接 GCC 的输入选项来自动理解,而不是由输出选项来理解:
当与库连接时,该库只能使用名称 foo 指定,其
-l
选项为-lfoo
:$ gcc ... -lfoo ...
-
在创建库时,必须指定完整文件名称
libfoo.so
或libfoo.a
。
其它资源
4.2. soname 机制
动态载入的库(共享对象)使用名为 soname 的 机制 来管理库的多个兼容版本。
先决条件
- 您必须了解动态链接和库。
- 您必须了解 ABI 兼容性的概念。
- 您必须了解库命名约定。
- 您必须了解符号链接。
问题简介
动态加载的库(共享对象)作为一个独立的可执行文件存在。这样便可在不更新依赖库的应用程序的情况下更新库。然而,这个概念会产生以下问题:
- 库的实际版本的识别
- 同一库的现有多个版本需要
- 信号每个多个版本的 ABI 兼容性
soname 机制
要解决这个问题,Linux 使用名为 soname 的机制。
foo
库版本 X.Y 在版本号中与其他值相同的 X 版本兼容 ABI。保持兼容性的小变化会增加 Y。破坏兼容性的主要更改会增加 X 的值。
实际的 foo
库版本 X.Y 作为文件 libfoo.so.x.y
。在库文件中,记录一个带有值为 libfoo.so.x
的 soname 来指示兼容性。
当构建应用程序时,链接器通过搜索文件 libfoo.so
来查找库。必须存在具有这个名称的符号链接,指向实际库文件。然后连接器从库文件中读取 soname,并将其记录到应用程序可执行文件中。最后,链接程序会创建应用程序,它使用 soname,而不是名称或文件名来声明对库的依赖。
当运行时动态链接程序在运行前链接应用程序时,它会从应用程序的可执行文件读取 soname。这个 soname 是 libfoo.so.x
。必须存在具有这个名称的符号链接,指向实际库文件。无论版本的 Y 组件是什么,都允许加载库,因为 soname 不会改变。
版本号的 Y 组件不仅限于一个数字。另外,有些库用它们的名称对版本进行编码。
从文件中读取 soname
显示库文件 somelibrary
的 soname
$ objdump -p somelibrary | grep SONAME
将 somelibrary 替换为您要检查的库的实际文件名。
4.3. 使用 GCC 创建动态库
允许动态链接的库(共享对象):
- 通过代码重复使用来管理资源
- 通过更轻松地更新库代码来提高安全性
按照以下步骤从源构建和安装动态库。
先决条件
- 您必须了解 soname 机制。
- GCC 必须安装到系统中。
- 您必须有库的源代码。
流程
- 使用库源进入目录。
使用所需独立代码选项
-fPIC
将每个源文件编译到对象文件中:$ gcc ... -c -fPIC some_file.c ...
对象文件的文件名与原始源代码文件相同,但它的扩展是
.o
。从对象文件中链接共享库:
$ gcc -shared -o libfoo.so.x.y -Wl,-soname,libfoo.so.x some_file.o ...
使用的主要版本号是 X,次版本号为 Y。
将
libfoo.so.x.y
文件复制到适当位置,系统动态链路器可以在其中找到该文件。在 Red Hat Enterprise Linux 中,库的目录为/usr/lib64
:# cp libfoo.so.x.y /usr/lib64
请注意,您需要 root 权限才能操作此目录中的文件。
为 soname 机制创建符号链接结构:
# ln -s libfoo.so.x.y libfoo.so.x # ln -s libfoo.so.x libfoo.so
其它资源
- Linux 文档项目 - Program library HOjan - 3。共享代理
4.4. 使用 GCC 和 ar 创建静态库
通过将对象文件转换为特殊类型的归档文件,可以创建用于静态链接的库。
出于安全考虑,红帽不建议使用静态链接。只在需要时才使用静态链接,特别是红帽提供的库。详情请查看 第 3.2 节 “静态和动态链接”。
先决条件
- GCC 和 binutils 必须安装在系统中。
- 您必须了解静态和动态链接。
- 具有作为库共享的功能的源文件可用。
流程
使用 GCC 创建中间对象文件。
$ gcc -c source_file.c ...
如果需要,请附加更多源文件。生成的对象文件共享文件名,但使用
.o
文件名扩展。使用
binutils
软件包中的ar
工具将对象文件切换到静态库(Archive)。$ ar rcs libfoo.a source_file.o ...
文件
libfoo.a
已创建。使用
nm
命令检查生成的归档:$ nm libfoo.a
- 将静态库文件复制到适当的目录中。
当与库连接时, GCC 会自动从
.a
文件名扩展识别该程序库是静态链接的归档。$ gcc ... -lfoo ...
其它资源
Linux 手册页, ar(1):
$ man ar