共享库搜索路径
基本原理
-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 |
| 设置 | 未设置 | 设置 | ${RPATH} => ${LD_LIBRARY_PATH} => /lib => /usr/lib |
| 设置 或 未设置 | 设置 | 设置 | ${LD_LIBRARY_PATH} => ${RUN_PATH} => /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


浙公网安备 33010602011771号