动态链接库的RPATH和RUNPATH解惑

来源:互联网 发布:淘宝运营费用 编辑:程序博客网 时间:2024/05/01 10:55

最近在使用SPP网络框架进行业务开发的时候,遭遇动态库搜索路径问题,为了避免其他同学继续在这方面浪费精力,简单整理了相关知识点。

【背景知识】

这里不打算深入链接器内部,简明扼要给出链接器进行动态库搜索的一些规则。


以上是man ld结果部分截图,这里着重澄清两个基本概念:"link time"(链接时)和"runtime"(运行时),比如常用的-L选项属于链接时,而-rpath,LD_LIBRARY_PATH都属于运行时。

很多运维同学倾向于使用LD_LIBRARY_PATH,但是个人认为这并不是一种好方法,因为LD_LIBRARY_PATH作用于全局,可能对其他程序造成未预期的影响。有兴趣的同学可以读一读《Why LD_LIBRARY_PATH is bad》,这篇文章有比较全面的分析。

【实践检验】

目录文件:


// main.c#include <dlfcn.h>typedef void (*FuncA)(void);int main(int argc, char *argv[]){    void *plugin = dlopen("./libfunc_a.so", RTLD_LAZY);    FuncA func = (FuncA)dlsym(plugin, "FuncA");    func();    return 0;}
// func_a.c#include <stdio.h>void FuncB(void);void FuncA(void){    printf("[%s]%s:%d\n", __FUNCTION__, __FILE__, __LINE__);    FuncB();}
// func_b_sys.c// func_b_user.c#include <stdio.h>void FuncB(void){    printf("[%s]%s:%d\n", __FUNCTION__, __FILE__, __LINE__);}
# Makefileall:    gcc -g -Wall -fPIC -shared -o libfunc_b_sys.so func_b_sys.c    gcc -g -Wall -fPIC -shared -o libfunc_b_user.so func_b_user.c    ln -sf /data/warezhou/test/ld/libfunc_b_sys.so /usr/lib64/libfunc_b.so    ln -sf /data/warezhou/test/ld/libfunc_b_user.so ./lib/libfunc_b.so    gcc -g -Wall -fPIC -shared -o libfunc_a.so func_a.c -lfunc_b    gcc -g -Wall -o main main.c -ldl    gcc -g -Wall -o main_rpath main.c -ldl -Wl,--rpath=./lib,--disable-new-dtags    gcc -g -Wall -o main_rpath_runpath main.c -ldl -Wl,--rpath=./lib,--enable-new-dtagsclean:    rm main main_rpath main_rpath_runpath    rm -rf *.so    rm -rf /usr/lib64/libfunc_b.so    rm -rf ./lib/*

 实验结果:





【原因分析】


上图关于动态库搜索路径的总结来自qt工程师的blog,有兴趣的同学可以阅读原文。简单来说,当可执行文件同时设置RPATH和RUNPATH时,两者同时失效。

查看SPP源码后,发现Makefile里面没有显式指定disable-new-dtags,而这个选项的默认值是平台相关的,我们公司老的suse默认关闭,而新的tlinux默认开启。所以导致发行包里的可执行文件同时设置了RPATH和RUNPATH,最终导致业务模块.so依赖的第三方.so查找不到。

当然,上述问题,通过设置libfunc_a.so的RPATH也是可以解决问题的,有兴趣的同学可以试一试,因为整个搜索过程是递归向上执行的。

0 0
原创粉丝点击