linux动态链接库的加载顺序

linux动态链接库的加载顺序:
它有5个地方会查找,

  1. 编译时指定的run path
  2. LD_LIBRARY_PATH 指定的地方
  3. ldconfig 指定的地方
  4. /lib
  5. /usr/lib

下面是测试实例,验证上面5句话。 (注: 用strace 会更好的看到加载顺序!!! --hjjdebug)


  1. 编写5个so源文件和1个测试文件

hjj@hjj-Inspiron:~/MyTest/temp$ cat pos1.c
#include <stdio.h>
 
void tellpos()
{
    printf("I am pos1\n");
}
hjj@hjj-Inspiron:~/MyTest/temp$ cat pos2.c
#include <stdio.h>
 
void tellpos()
{
    printf("I am pos2\n");
}
hjj@hjj-Inspiron:~/MyTest/temp$ cat pos3.c
#include <stdio.h>
 
void tellpos()
{
    printf("I am pos3\n");
}
hjj@hjj-Inspiron:~/MyTest/temp$ cat pos4.c
#include <stdio.h>
 
void tellpos()
{
    printf("I am pos4\n");
}
hjj@hjj-Inspiron:~/MyTest/temp$ cat pos5.c
#include <stdio.h>
 
void tellpos()
{
    printf("I am pos5\n");
}
hjj@hjj-Inspiron:~/MyTest/temp$ cat main.c
#include <stdio.h>
void tellpos();
int main(int argc, char *argv)
{
	tellpos();
	return 0;
}
  1. 生成5个so文件并放到5个地方,生成test 测试文件
$ cat Makefile
CC=gcc
CFLAG=-fPIC -c
LDFLAG=-shared
all: fivepos test
fivepos
	-mkdir pos1 pos2 pos3
	$(CC) $(CFLAG) -o pos.o pos1.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	mv libpos.so pos1
	$(CC) $(CFLAG) -o pos.o pos2.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	mv libpos.so pos2
	$(CC) $(CFLAG) -o pos.o pos3.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	mv libpos.so pos3
	$(CC) $(CFLAG) -o pos.o pos4.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	sudo mv libpos.so /lib
	$(CC) $(CFLAG) -o pos.o pos5.c
	$(CC) $(LDFLAG) pos.o -o libpos.so
	sudo mv libpos.so /usr/lib
test: main.c
	gcc -o test main.c -L pos1 -lpos -Wl,-rpath,pos1
# -L pos1 是说连接时到 pos1 目录去找
# -Wl,-rpath,pos1 是说运行时到pos1目录去找 
  1. 其它说明:
    pos1 通过readelf -d test 可以看到(RPATH) Library rpath: [pos1]
    pos2 需要用LD_LIBRARY_PATH 说明。此例为: export LD_LIBRARY_PATH=./pos2
    pos3 需要在/etc/ld.so.conf 中指明,此例为:/home/hjj/MyTest/temp/pos3
    然后ldconfig 生成缓存使设置生效。
    pos4 系统目录/lib
    pos5 系统目录/usr/lib

  1. 用ldd 检查 和用 ./test 直接测试及结果

那个64为地址是动态地址,每次ldd 都会变的。
ldd test
libpos.so => pos1/libpos.so (0x00007f93f4204000)
./test
I am pos1
rm pos1/libpos.so // 第一个地方删除掉该so, 它会从剩下的4个地方继续选择

ldd test
libpos.so => ./pos2/libpos.so (0x00007f580053d000)
./test
I am pos2
rm pos2/libpos.so //它会从剩下的3个地方继续选择

$ ldd test
libpos.so => /home/hjj/MyTest/temp/pos3/libpos.so (0x00007efef7dbf000)
$ ./test
I am pos3
rm pos3/libpos.so //它会从剩下的2个地方继续选择

ldd test
libpos.so => /lib/libpos.so (0x00007f70d60ce000)
./test
I am pos4
sudo rm /lib/libpos.so //它会从剩下的1个地方继续选择

ldd test
libpos.so => /usr/lib/libpos.so (0x00007f3849e1e000)
./test
I am pos5
sudo rm /usr/lib/libpos.so

ldd test
libpos.so => not found
./test
error while loading shared libraries: libpos.so: cannot open shared object file: No such file or directory

我们用strace ./test 来跟踪系统调用,非常清晰的看到了动态库的加载过程。(这就不贴文字了). 看到链接器经过了很多的努力后,
最后给出找不到动态库的结论。
本贴演示了如何生成动态库so文件及如何使用动态库。 给出了一种比较笨的直接了当的方法,也给出了聪明的strace方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值