共享库搜索路径

基本原理

-L编译选项是编译期间使用

LD_LIBRARY_PATH环境变量是运行期间使用,可以用来指定so的加载路径,并且优先级高于系统默认的。

RPATHRUNPATH是ELF格式里面的一个数据,rpath编译选项实际上是在可执行文件中加入了RUNPATH或者RPATH

小结一下一个ELF文件自身加载so的情况(不可信,仅供参考):

其实这三者的关系概括起来没有几点:

  1. LD_LIBRARY_PATH是个环境变量,优先级高于系统默认的。
  2. RPATH是ELF格式里面的一个数据,他的优先级比LD_LIBRARY_PATH还要高
  3. 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

参考文档

RPATH和RUNPATH区别 - 简书 (jianshu.com)

RPATH RUNPATH 和 LD_LIBRARY_PATH_pkpkpk的专栏-CSDN博客

posted @ 2023-06-18 22:32  devin1024  阅读(53)  评论(0)    收藏  举报