在使用 c 或 c 开发应用时在启动程序时有时会遇到这个错误找不到动态库。这个时候我们使用 ldd 来查看发现可执行文件依赖的动态库显示为 not found。1 实验代码使用如下 3 个文件做实验。hello.h 中声明了函数 say_hello()。hello.c 中实现了函数 say_hallo() 在函数中打印 hellohello.c 编译出一个动态库。main.c 中调用 hello.c 中的函数 say_hello()main.c 编译出可执行文件。hello.h:void say_hello();hello.c#include stdio.h #include hello.h void say_hello() { printf(hello\n); }main.c#include hello.h int main() { say_hello(); return 0; }使用 gcc -fPIC -shared hello.c -o libhello.so 编译出动态库使用 gcc main.c libhello.so 编译可执行文件编译之后的文件目录如下libhello.so 是动态库a.out 是可执行文件。这个时候直接执行 a.out 却无法执行打印错误信息是找不到动态库。除了使用 ldd 查看文件依赖的动态库之外还可以使用 objdump 或 readelf 来查看可执行文件依赖的动态库。objdump -x a.out |grep NEEDreadelf -d a.out |grep NEED2 动态库路径配置有几种方式可以配置动态库的路径这几种方式都是可行的其中 LD_LIBRARY_PATH 是工作中最常使用的。2.1 LD_LIBRARY_PATH工作中我们常用的是设置一个环境变量 LD_LIBRARY_PATH将依赖的动态库路径追加到这个环境变量中可执行文件就可以执行了。在执行可执行文件时linux 加载器会从这个环境变量所包含的路径中找动态库。如下图所示将 libhello.so 追加到环境变量使用 ldd 查看 a.out 依赖的库也不会显示 not found 了执行 a.out 也可以正确执行。2.2 /etc/ld.so.conf.d/先看看这个目录下默认有什么文件。可以看到有 3 个 .conf 文件文件中的内容分别是 /usr/local/lib/lib/x86_64-linux-gnu、/usr/lib/x86_64-linux-gnu/usr/lib/x86_64-linux-gnu/libfakeroot。这个目录下配置的路径下的动态库会被查找到。在该目录下配置的路径下的动态库可以通过ldconfig -p查看到。如果要把本文中的 libhello.so 也加入到这个目录下操作如下1首先在目录下增加一个 .conf 文件文件名没有要求只要不重复就可以文件里写入 libhello.so 所在的目录2执行ldconfig添加配置之后执行 ldconfig 才会生效执行完两个步骤之后使用 ldconfig -p 就可以看到 libhello.so 出现在缓存里了。2.3 编译时添加路径在编译的时候使用 -Wl,rpath 来添加动态库路径。其中 rpath 是 run path 的意思使用 rpath 指定的路径在加载时会到这个路径下查找动态库。gcc main.c -lhello -L. -Wl,-rpath /home/wyl/test/libtest/使用上边的命令编译之后使用 ldd 查看 a.out 依赖的动态库能够找到 libhello.so。使用 objdump 可以看到这个路径被直接写到了 a.out 文件中。3 不同配置下的动态库查找顺序LD_DEBUG 可以用来查看链接和加载过程的信息用来调试。LD_DEBUG 可以赋不同的值不同的值可以查看不同的调试信息。我们使用 libs 来显示库的加载信息。在实验之前做如下工作1编译时使用 rpath 选项这样的话就会将 /home/wyl/test/libtest/ 写到编译的目标文件中gcc main.c -lhello -L. -Wl,-rpath /home/wyl/test/libtest/2配置 LD_LIBRARY_PATHexport LD_LIBRARY_PATH/home/wyl/test/libtest/lib1:$LD_LIBRARY_PATH3配置 /etc/ld.so.conf.d/hello.conf这样的话3 种方式都做了配置但是 3 个方式配置的路径是不一样的。同时我们只让 libhello.so 存在于 /home/wyl/test/libtest/lib2 中另外两个目录下不放 libhello.so。使用 LD_DEBUG 的打印信息如下从打印信息可以看出来1首先查找的路径是 LD_LIBRARY_PATH 中的路径2LD_LIBRARY_PATH 路径找不到从 rpath 选项中的路径查找3rpath 路径找不到则从 /etc/ld.so.cache 中查找该文件中保存的就是配置在 /etc/ld.so.conf.d/ 中配置的目录下的动态库没有交警的时候以红绿灯为准有交警的时候以交警为准。LD_LIBRARY_PATH需要用户专门设置属于最后的用户行为当然是最优先使用的类似于交警/etc/ld.so.cache属于系统配置是一种兜底行为类似于红绿灯。系统的是兜底的是最后的行为用户的是最上层的是最开始优先的行为。