Linux动态库的查找路径

前两天写了一个动态库,然后试图编译到程序里面去运行,结果发现编译的时候通过gcc的-L参数来指定路径仅仅能让编译通过,运行时还是会出问题的。

比如下面这个例子:

main.c是主程序,sum.c中间含有一个函数add,用来执行加法,代码如下:

复制代码
 1 /*
 2  *  main.c
 3  */
 4 #include <stdio.h>
 5 
 6 int add(int a, int b);
 7 
 8 int main(int argc,char *argv[])
 9 {
10     printf("sum = %d\n", add(3,5));
11     return 0;
12 }
复制代码

 

复制代码
1 /*
2  * sum.c
3  */
4 int add(int a, int b)
5 {
6     return a + b;
7 }
复制代码

 

出错结果如下图所示:

我在编译的时候通过-L指定了查找动态库的位置,结果运行的时候还是找不到我自己写的那个libsum.so这个动态库,后来去查了一下,才明白其中原委。

程序在链接动态库的时候分为2步,编译时链接和运行时链接。

1. 编译时链接

  这个过程是由ld程序来执行的,所以编译时找不到动态库的位置的话,经常就会看到这种错误:

  

  这个过程严格意义上来说并不能说是链接,因为在这里ld程序并没有真正的把库里面的函数的执行代码写到可执行文件里面,只是把一些符号还有其他的必要信息写道了可执行文件里面,供可执行文件运行时查找。

  总的来说,ld在这一步里面就是做了两个事情:

  1. 查找动态库中是否含有我们需要的符号(函数和全局变量),如果都能找到,则链接允许通过,生成了可执行文件。

  2. 在可执行文件中写入了符号和其他必要的信息(例如符号的地址),供可执行文件运行时查找。

2. 运行时链接

  这个过程是由ld-linux.so程序来执行,这个才是真正的链接。它所做的工作就是将动态库的代码映射到进程(可执行文件运行起来就是进程啦...)的虚拟地址空间中,供进程来调用。

 

关于链接,加载,运行的更多信息可以参看<参考文章1>(详细地址见本文最后)。

 

OK,明白了上面两个链接之后,我们再来看这两个链接查找动态库的目录位置,如下:

运行时,ld-linux.so查找共享库的顺序

(1)ld-linux.so.6在可执行的目标文件中被指定,可用readelf命令查看 


(2)ld-linux.so.6缺省在/usr/lib和lib中搜索;当glibc安装到/usr/local下时,它查找/usr/local/lib


(3)LD_LIBRARY_PATH环境变量中所设定的路径 


(4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路径,由ldconfig生成二进制的ld.so.cache中

编译时,ld-linux.so查找共享库的顺序

(1)ld-linux.so.6由gcc的spec文件中所设定 


(2)gcc --print-search-dirs所打印出的路径,主要是libgcc_s.so等库。可以通过GCC_EXEC_PREFIX来设定 


(3)LIBRARY_PATH环境变量中所设定的路径,或编译的命令行中指定的-L/usr/local/lib 


(4)binutils中的ld所设定的缺省搜索路径顺序,编译binutils时指定。(可以通过“ld --verbose | grep SEARCH”来查看) 


(5)二进制程序的搜索路径顺序为PATH环境变量中所设定。一般/usr/local/bin高于/usr/bin


(6)编译时的头文件的搜索路径顺序,与library的查找顺序类似。一般/usr/local/include高于/usr/include

 

大家注意编译时查找的路径可以通过gcc -L参数或者LIBRARY_PATH来指定,但是运行时的查找路径却不包含gcc -L和LIBRARY_PATH环境变量指定的路径,所以这样就会出现我们刚开始所说的那个问题,编译时通过-L指定了动态库的搜索路径,编译也通过了,但是运行时却会报错,这是因为运行时查找动态库的路径还没指定,所以我们自己写的动态库就找不到了,而要解决这个问题,通过设置环境变量LD_LIBRARY_PATH或者修改/etc/ld.so.conf(记得修改完了运行ldconfi来生成ld.so.cache)就可以了。如下图所示:

 

参考文章:

1.  C编译器、链接器、加载器详解

2.  ld-linux.so查找共享库的顺序

3.  readelf命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 动态库搜索路径是指在 Linux 系统下,动态接器(ld)搜索和加载共享(.so)时,按照一定的优先级和搜索路径查找目标共享的过程。 在 Linux 中,系统动态共享存放路径一般有如下几个: 1. /usr/lib:系统提供的共享路径,一些常用的共享会被安装在该目录下。 2. /lib:系统提供的另一个共享路径,类似于 /usr/lib,但一些重要的共享会被安装在该目录下,这些通常是系统引导过程中需要的。 3. LD_LIBRARY_PATH 环境变量:如果设置了该环境变量,ld 将会在其所指定的路径查找共享,而不是在默认路径查找。 4. /etc/ld.so.conf 文件:该文件指定了需要搜索的共享路径,如果没有指定,ld 会使用默认路径搜索共享。 5. /etc/ld.so.cache 文件:该文件记录了系统中已经安装的共享和其路径信息,ld 可以通过该文件快速查找共享,避免搜索时的性能损失。 在进行动态共享接时,系统动态接器会按照以上搜索路径的优先级从上至下查找目标共享。如果要修改默认的动态库搜索路径,可以在 /etc/ld.so.conf 中添加自定义路径,并运行 ldconfig 命令更新缓存信息。 总之,动态库搜索路径Linux 下非常重要的概念,对于程序员和系统管理员而言,了解动态库搜索路径有助于更好地管理系统共享,提高应用程序的可用性和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值