目录
[1. 引言](#1. 引言)
[2. 动态库的特点](#2. 动态库的特点)
[3. 制作动态库](#3. 制作动态库)
[3.1 编译位置无关代码(PIC)](#3.1 编译位置无关代码(PIC))
[3.2 生成动态库](#3.2 生成动态库)
[3.3 查看动态库信息](#3.3 查看动态库信息)
[4. 使用动态库](#4. 使用动态库)
[4.1 编译可执行文件](#4.1 编译可执行文件)
[4.2 运行时库搜索路径](#4.2 运行时库搜索路径)
[5. 动态库的版本管理](#5. 动态库的版本管理)
[6. 动态库的优缺点总结](#6. 动态库的优缺点总结)
[7. 小结](#7. 小结)
1. 引言
动态库(Shared Library)是Linux下更常用的库形式。它允许多个进程共享内存中的同一份库代码,从而节省内存和磁盘空间。本文详细介绍动态库的制作、编译链接、运行时查找路径配置以及相关工具的使用。
2. 动态库的特点
-
编译链接时,可执行文件中只记录库函数的符号引用,不复制库代码。
-
运行时,由动态链接器(
ld-linux.so)负责加载动态库并完成符号重定位。 -
多个进程可以共享物理内存中的同一份动态库代码(通过虚拟内存映射)。
-
优点:节省磁盘和内存;库升级时无需重新链接可执行文件。
-
缺点:部署时需要保证目标系统存在兼容的动态库;加载时有额外开销。
3. 制作动态库
使用 gcc 的 -shared 和 -fPIC 选项。
3.1 编译位置无关代码(PIC)
bash
gcc -fPIC -c my_stdio.c my_string.c
-fPIC:生成位置无关代码(Position Independent Code)。由于动态库加载地址不确定,代码必须使用相对寻址,才能在任意地址正确执行。
3.2 生成动态库
bash
gcc -shared -o libmystdio.so my_stdio.o my_string.o
-
-shared:生成共享库(动态库)。 -
库名格式:
libxxx.so。
也可一步完成:
bash
gcc -shared -fPIC -o libmystdio.so my_stdio.c my_string.c
3.3 查看动态库信息
bash
file libmystdio.so
# 输出:ELF 64-bit LSB shared object
readelf -h libmystdio.so
# 查看ELF头,Type为 DYN (Shared object file)
4. 使用动态库
4.1 编译可执行文件
bash
gcc main.c -L. -lmystdio -o myapp
此时生成的可执行文件 myapp 依赖于 libmystdio.so。通过 ldd 命令查看:
bash
ldd myapp
输出示例:
text
linux-vdso.so.1 (0x00007fff4d396000)
libmystdio.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007fa2aef30000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa2af2fe000)
可以看到 libmystdio.so 没有被找到,因为动态链接器默认只在系统库路径中搜索。
4.2 运行时库搜索路径
动态链接器(ld-linux.so)按照以下顺序查找动态库:
-
可执行文件中指定的
DT_RPATH(已废弃)。 -
环境变量
LD_LIBRARY_PATH。 -
配置文件
/etc/ld.so.conf指定的路径(由ldconfig生成缓存/etc/ld.so.cache)。 -
默认系统路径
/lib、/usr/lib、/lib64等。
解决方案:
方法一:临时修改环境变量
bash
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./myapp
方法二:安装到系统路径
bash
sudo cp libmystdio.so /usr/local/lib/
sudo ldconfig # 更新缓存
方法三:修改配置文件
bash
echo "/path/to/your/lib" | sudo tee /etc/ld.so.conf.d/myapp.conf
sudo ldconfig
方法四:编译时指定 -rpath
bash
gcc main.c -L. -lmystdio -Wl,-rpath,. -o myapp
-Wl,-rpath,. 将当前目录写入可执行文件的 DT_RUNPATH,运行时动态链接器会搜索该路径。
5. 动态库的版本管理
Linux 动态库通常采用 soname 机制:
-
真实文件名:
libmystdio.so.1.0.0 -
soname:
libmystdio.so.1 -
链接器名:
libmystdio.so
创建软链接:
bash
ln -s libmystdio.so.1.0.0 libmystdio.so.1
ln -s libmystdio.so.1 libmystdio.so
编译时使用 -Wl,-soname,libmystdio.so.1 设置 soname。
6. 动态库的优缺点总结
| 优点 | 缺点 |
|---|---|
| 可执行文件体积小 | 部署需注意库依赖 |
| 内存中多进程共享 | 运行时加载有性能开销 |
| 库升级方便(只需替换.so) | 版本不兼容可能导致程序崩溃 |
7. 小结
本文详细讲解了动态库的制作、使用以及运行时查找机制。掌握了 -fPIC、-shared、LD_LIBRARY_PATH、ldconfig 等概念,就能熟练管理Linux下的动态库。下一篇我们将深入ELF文件格式,剖析目标文件和可执行文件的内部结构。