跳到主要内容

动态链接库


动态链接库


一、/etc/ld.so.conf.d 的作用

  • 动态库路径管理:系统会读取该目录下的 .conf 文件,这些文件指定了动态链接库的额外搜索路径。
  • 配置动态库缓存:在运行程序时,动态链接器会从这些路径中查找所需的库。

默认加载的路径(视系统配置而定):

  1. /lib
  2. /usr/lib
  3. /usr/local/lib

通过 /etc/ld.so.conf.d,可以扩展默认路径。


二、动态库的加载顺序

以 Linux / glibc 的常见 ELF 程序为例,所需库名不含斜杠时,搜索顺序通常涉及:

  1. 存在 DT_RPATH 且没有 DT_RUNPATH 时,使用 DT_RPATH。
  2. LD_LIBRARY_PATH;安全执行模式下可能被忽略。
  3. DT_RUNPATH,主要用于该对象直接依赖的库。
  4. /etc/ld.so.cache 中记录的匹配项。
  5. 系统默认库目录,具体路径与架构、系统构建有关。

依赖名称已经包含斜杠时会按相应路径处理,不能再套用这份搜索列表。动态链接器不是每次运行都重新解析 ld.so.conf.d;这些配置通常由 ldconfig 读入并更新缓存。

还要区分两个阶段:编译链接阶段由 -L、-l 等选项寻找输入库;程序启动时再由动态加载器寻找运行所需库。运行时缓存配置不能代替编译命令中的 -L。


三、/etc/ld.so.conf.d 的文件结构

该目录包含多个 .conf 文件,每个文件可以指定一组路径。例如:

# 查看 /etc/ld.so.conf.d 内容
ls /etc/ld.so.conf.d

输出示例:

glibc.conf
x86_64-linux-gnu.conf
local.conf

文件示例:

  • /etc/ld.so.conf.d/local.conf:
    /usr/local/lib
    /opt/custom/lib

这些路径会被动态链接器添加到库搜索路径中。


四、如何配置动态库路径

1. 添加自定义路径

假设有一个自定义动态库路径 /home/user/mylibs,以下是配置步骤:

  1. 创建配置文件:
    sudo nano /etc/ld.so.conf.d/mylibs.conf
    添加如下内容:
    /home/user/mylibs
  2. 更新动态库缓存:
    sudo ldconfig
  3. 验证是否生效: 查看是否包含新路径:
    ldconfig -p | grep mylibs

2. 临时配置路径

如果只是临时测试动态库路径,可以使用 LD_LIBRARY_PATH 环境变量:

export LD_LIBRARY_PATH="/home/user/mylibs${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
./myprogram

注意:这种方法作用于当前终端及其子进程。上面的条件拼接避免在原变量为空时留下空路径段;空路径段可能把当前工作目录加入搜索。


五、ldconfig 的作用

ldconfig 是管理动态库缓存的工具,其作用包括:

  1. 扫描路径:读取 /etc/ld.so.conf;只有它通过 include 引入相应文件时,才会读取 ld.so.conf.d 中的配置。
  2. 更新缓存:生成 /etc/ld.so.cache 文件,加速库的加载。

常用命令

  1. 更新缓存:
    sudo ldconfig
  2. 指定路径更新缓存:
    sudo ldconfig /home/user/mylibs
  3. 查看当前缓存的库:
    ldconfig -p

六、动态库配置实例

1. 动态库开发

创建一个简单动态库:

// hello.c
#include <stdio.h>

void hello(void) {
    printf("Hello, from dynamic library!\n");
}

编译成动态库:

gcc -fPIC -shared -o libhello.so hello.c

将动态库移动到 /opt/mylibs:

sudo mkdir -p /opt/mylibs
sudo cp libhello.so /opt/mylibs/

2. 配置加载路径

创建 /etc/ld.so.conf.d/mylibs.conf:

sudo nano /etc/ld.so.conf.d/mylibs.conf

内容:

/opt/mylibs

更新缓存:

sudo ldconfig

3. 使用动态库

编写一个测试程序:

// main.c
void hello(void);

int main(void) {
    hello();
    return 0;
}

编译并运行:

gcc -o main main.c -L/opt/mylibs -lhello
./main

输出:

Hello, from dynamic library!

七、排错方法

  1. 检查动态库是否存在:
    ldconfig -p | grep libhello
  2. 验证动态库路径是否正确:
    ldd ./main
  3. 动态库无法加载时:
    • 检查是否添加了正确的路径到 /etc/ld.so.conf.d。
    • 检查是否运行了 ldconfig。

这里的 -L/opt/mylibs 解决链接阶段查找 libhello.so,上文的 ldconfig 配置解决运行阶段查找;缺少其中一环可能分别出现 cannot find -lhello 或 error while loading shared libraries。只对可信的本地程序使用 ldd;检查不可信文件可先用 readelf -d 查看静态依赖信息。

参考:Linux 动态加载器手册、GCC 链接选项。


文章作者: 0xdadream
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 0xdadream !
赏
评论

评论将在接近此处时加载,也可点击立即加载。

  目录