【Linux】动态库的制作、使用与运行时查找

目录

[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)按照以下顺序查找动态库:

  1. 可执行文件中指定的 DT_RPATH(已废弃)。

  2. 环境变量 LD_LIBRARY_PATH

  3. 配置文件 /etc/ld.so.conf 指定的路径(由 ldconfig 生成缓存 /etc/ld.so.cache)。

  4. 默认系统路径 /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-sharedLD_LIBRARY_PATHldconfig 等概念,就能熟练管理Linux下的动态库。下一篇我们将深入ELF文件格式,剖析目标文件和可执行文件的内部结构。