Linux程序加载动态链接库的搜索路径

Linux与Windows都支持动态链接库,Windows下是dll文件,Linux下是so文件,
如果程序执行时没有找到需要的动态链接库,Windows下会出现提示框,Linux下会提示:
error while loading shared libraries: xxx.so: cannot open shared object file: No such file or directory
这都是因为按照一定的规则,可执行程序没有找到某个库文件
Windows下可执行文件运行时会在当前目录和系统目录以及PATH环境变量的目录列表中搜索dll文件,而Linux环境下有些差异,具体加载顺序总结如下:

  1. ELF可执行文件中动态段DT_RPATH指定;gcc加入链接参数“-Wl,-rpath”指定动态库搜索路径;
  2. 环境变量LD_LIBRARY_PATH指定路径;
  3. /etc/ld.so.cache中缓存的动态库路径。可以通过修改配置文件/etc/ld.so.conf
    增删路径(修改后需要运行ldconfig命令);
  4. 默认的 /lib/;
  5. 默认的 /usr/lib/

详细的:

  • 4和5比较好理解,只需将so文件放入/lib或/usr/lib下,可执行文件就能找到它;

  • 2有点类似Windows下PATH环境变量的作用:

    设定LD_LIBRARY_PATH:export LD_LIBRARY_PATH=./
    不好的地方在于,在当前环境上下文中,所有的可执行文件运行时都会先搜索一边当前目录
    取消LD_LIBRARY_PATH值的设定:unset LD_LIBRARY_PATH

  • 3是通过修改ld的配置来设定可执行文件搜索动态链接库的路径,同样是一种全局效果

  • 如果能确定动态链接库文件与可执行文件的相对路径,使用1是最合适的,它将搜索行为编译到了可执行文件中

    举例:
    // foo.c
    int add(int a, int b){ return a + b; }
    #编译为动态链接库
    #gcc foo.c -shared -o libfoo.so

    // main.c
    extern add(int a, int b);
    int main(){ return add(1, 2); }
    #编译为可执行文件,并指定需要动态链接libfoo.so
    #gcc main.c -L./ -lfoo -Wl,rpath=./
    #说明:-L./ 指定编译时动态链接库的路径
    -lfoo 指定需要链接libfoo.so这个库
    -Wl,rpath=./ 最关键的,将搜索路径编译到可执行程序中

另外:关于查看程序依赖的动态链接库,Windows下可以使用Dependency Walker,Linux下可以使用ldd命令,如:ldd ./a.out

你可能感兴趣的:(C++,Linux)