共享库搜索路径
基本原理
-L
编译选项是编译期间使用
LD_LIBRARY_PATH
环境变量是运行期间使用,可以用来指定so的加载路径,并且优先级高于系统默认的。
RPATH
和RUNPATH
是ELF格式里面的一个数据,rpath
编译选项实际上是在可执行文件中加入了RUNPATH
或者RPATH
。
小结一下一个ELF文件自身加载so的情况(不可信,仅供参考):
其实这三者的关系概括起来没有几点:
LD_LIBRARY_PATH
是个环境变量,优先级高于系统默认的。RPATH
是ELF格式里面的一个数据,他的优先级比LD_LIBRARY_PATH
还要高RUNPATH
很特殊,如果他出现了RPATH
就躲起来了,LD_LIBRARY_PATH
又成了首选??
ELF 中 RPATH | ELF 中 RUNPATH | LD_LIBRARY_PATH 变量 | 尝试加载目录的顺序 |
---|---|---|---|
未设置 | 未设置 | 未设置 | /lib => /usr/lib |
未设置 | 未设置 | 设置 | ${LD_LIBRARY_PATH} => /lib => /usr/lib |
设置 | 未设置 | 未设置 | ${RPATH} => /lib => /usr/lib |
设置 | 未设置 | 设置 | |
设置 或 未设置 | 设置 | 设置 | |
设置 或 未设置 | 设置 | 未设置 | ${RUN_PATH} => /lib => /usr/lib |
LD_LIBRARY_PATH 例子
// a.c #include <stdio.h> extern void test_b(); void test_a() { test_b(); } int main() { test_a(); return 0; } // b.c #include <stdio.h> void test_b() { }
root@ubuntu:/usr1/tmp/2# gcc b.c -shared -fPIC -o lib/libmyb.so root@ubuntu:/usr1/tmp/2# gcc -o a a.c -Llib -lmyb root@ubuntu:/usr1/tmp/2# root@ubuntu:/usr1/tmp/2# ./a ./a: error while loading shared libraries: libmyb.so: cannot open shared object file: No such file or directory root@ubuntu:/usr1/tmp/2# root@ubuntu:/usr1/tmp/2# export LD_LIBRARY_PATH=lib root@ubuntu:/usr1/tmp/2# ./a root@ubuntu:/usr1/tmp/2# root@ubuntu:/usr1/tmp/2# tree
RPATH和RUNPATH 例子
// a.c #include <stdio.h> extern void test_b(); void test_a() { test_b(); } int main() { test_a(); return 0; } // b1.c, b2.c #include <stdio.h> void test_b() { printf("test_b in: %s\n", __FILE__); }
unset LD_LIBRARY_PATH gcc b1.c -shared -fPIC -o lib1/libmyb.so gcc b2.c -shared -fPIC -o lib2/libmyb.so gcc -o a a.c -Llib1 -lmyb -Wl,-rpath=lib2 tree ldd ./a readelf -d ./a | grep PATH export LD_LIBRARY_PATH=lib1 ldd ./a readelf -d ./a | grep PATH
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具