Linux 编译、运行阶段 动态链接库的查找路径

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35865125/article/details/87868653

首先,动态链接库的概念,生成方法,参照:我的文章的 Library Files 部分。

如果程序需要使用某个动态链接库中的函数,则,在程序的编译阶段和之后的运行阶段都需要这个动态链接库, 即 编译时链接和运行时链接

1. 编译时链接

  这个过程是由ld(链接器)来执行的。ld查找动态库中是否含有我们需要的符号(eg.函数),如果都能找到,则链接允许通过,生成可执行文件,否则报错。   在这里ld程序并没有真正把库里面的函数的执行代码写到可执行文件里面,只是把一些符号还有其他的必要信息写道了可执行文件里面,供可执行文件运行时查找。

 编译时,动态链接库的查找路径可以进行指定。例如,

gcc -L xxx ,意味着除了在系统默认的路径下搜索动态链接库之外,还会在-L指定的xxx路径下搜索。

gcc  -rpath-link xxx:这个也是用于指定一个“链接”的时候的搜索路径,例如你显示指定的需要 FOO.so,但是 FOO.so 本身是需要 BAR.so 的,后者你并没有指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。

编译时,ld-linux.so查找共享库的顺序(需看ld手册):

(1)ld-linux.so.x由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来指定,但是这对运行时的查找路径是不起作用的!-L只是指定了程序编译连接时库的路径,并不影响程序执行时搜索库的路径。

2. 运行时链接

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


程序在连接时使用了共享库,就必须在运行的时候能够找到共享库的位置。linux的可执行程序在执行的时候默认是先搜索/lib和/usr/lib这两个目录,然后按照/etc/ld.so.conf里面的配置搜索绝对路径。同时,Linux也提供了环境变量LD_LIBRARY_PATH供用户选择使用,用户可以通过设定它来查找除默认路径之外的其他路径,LD_LIBRARY_PATH路径优先于系统默认路径之前查找.

LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。通常情况下推荐还是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路径查找库,避免了使用LD_LIBRARY_PATH环境变量查找!!(看到Qt的使用qmake生成的makefile中,有gcc -rpath xxx,指出程序运行时的一个搜索路径, 或许与qt的QMAKE_RPATHDIR有关

ld-linux.so.x在可执行的目标文件中被指定,可用readelf -l命令查看 。

 (很多现代应用都是通过动态编译链接的,当一个 需要动态链接 的应用被操作系统加载时,系统必须要 定位 然后 加载它所  需要的所有动态库文件。 在Linux环境下,这项工作是由ld-linux.so.x来负责完成的)
和Windows下的PE文件类似,ELF文件是
linux系统下可执行文件、动态库文件、静态库文件的标准格式。

例如,运行readelf -l  文件名,在输出的Headers部分的INTERP部分,会指出该可执行文件需要的ld-linux.so。

运行时,ld-linux.so 查找共享库的路径:
(1)gcc的-R或-rpath选项 指定的路径。

(2)LD_LIBRARY_PATH环境变量中所设定的路径
(3)ld-linux.so 缺省在/usr/lib和lib中搜索;当glibc安装到/usr/local下时,它查找/usr/local/lib
(4)/etc/ld.so.conf(或/usr/local/etc/ld.so.conf)中所指定的路径。 (查看/etc/ld.so.conf文件:或许只有一行:“include /etc/ld.so.conf.d/*.conf ”,意味着包括了/etc/ld.so.conf.d/目录下的所有.conf文件,每个文件中都写着具体的路径。如果你想加一个运行时的搜索路径,可在/etc/ld.so.conf.d目录下新建一个.conf文件,里面写上路径,注意添加完了之后要在root权限下运行ldconfig指令,使其生效,该指令更新记录了系统中有哪些so文件的缓存文件(/etc /ld.so.cache


其他:

可使用ldd指令查看一个可执行文件依赖于哪些库:ldd  xxx

例如:


Ref:

https://www.cnblogs.com/bwangel23/p/4695342.html

 https://www.cnblogs.com/ch459742906/p/7245783.html

https://blog.csdn.net/ck404/article/details/69637673

https://blog.csdn.net/faithzzf/article/details/68064918

https://www.cnblogs.com/leaven/p/6363787.html

https://blog.csdn.net/king523103/article/details/50681669

https://www.cnblogs.com/Anker/p/3527677.html


猜你喜欢

转载自blog.csdn.net/qq_35865125/article/details/87868653