linux动态库加载时搜索路径
摘自http://gotowqj.iteye.com/blog/1926613
对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading shared libraries”这样的错误,这是典型的因为需要的动态库不在动态链接器ld.so的搜索路径设置当中导致的。
具体说来,动态链接器ld.so按照下面的顺序来搜索需要的动态共享库:
1.ELF可执行文件中动态段中DT_RPATH所指定的路径。这实际上是通过一种不算很常用,却比较实用的方法所设置的:编译目标代码时,可以对gcc加入链接参数“-Wl,-rpath”指定动态库搜索路径;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3./etc/ld.so.cache中所缓存的动态库路径(如果支持ld.so.cache的话)。这可以通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径来改变;
4.默认的动态库搜索路径/lib;
5.默认的动态库搜索路径/usr/lib。
在嵌入式Linux系统的实际应用中,1和2被经常使用,也有一些相对简单的的嵌入式系统会采用4或5的路径来规范动态库。3在嵌入式系统中使用的比较少,因为有很多系统根本就不支持ld.so.cache。
4和5的方式非常简单,只要将所需要的库放到/lib或/usr/lib就可以解决找不到库的问题,不过对于大一些的系统来说,不太方便管理。1和2的方式要稍微复杂一些,下面我们用一个非常简单的例子来说明如何应用。
首先编写一个最简单的动态共享库,源代码pirnt.c如下:
| 1 #include <stdio.h> 2 3 void print_foo() 4 { 5 printf("fooooooooo\n"); 6 } |
注意将它编译成共享库:
| # gcc print.c -shared -o libprint.so # file libprint.so libprint.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped |
调用该共享库main.c代码如下:
| 1 #include <stdio.h> 2 3 extern void print_foo(); 4 5 int main() 6 { 7 print_foo(); 8 9 return 0; 10 } |
编译之后的运行结果如下:
| # gcc main.c -L./ -lprint -o pfoo # ./pfoo ./pfoo: error while loading shared libraries: libprint.so: cannot open shared object file: No such file or directory |
这便是典型的找不到动态库的错误。通常我们可以通过设置环境变量LD_LIBRARY_PATH来指定动态库的搜索路径(即上面的方法2),比如这样就可以正确运行了:
| # export LD_LIBRARY_PATH=./ # ./pfoo fooooooooo |
但这种方法有一个明显的缺点:一旦LD_LIBRARY_PATH被设定,则在这个环境变量生效的范围之内,所有其他的ELF可执行程序也会按照这个顺序去搜索动态库,这样势必会造成搜索时的一些浪费。
我们也可以使用另外一种方案来解决这种问题,即利用参数“-Wl,-rpath”在编译时指定运行时的搜索路径(即上面的方法1),如下所示:
| # unset LD_LIBRARY_PATH # echo $LD_LIBRARY_PATH # gcc main.c -L./ -lprint -o pfoo_r -Wl,-rpath=./ # ./pfoo ./pfoo: error while loading shared libraries: libprint.so: cannot open shared object file: No such file or directory # ./pfoo_r fooooooooo |
我们首先unset了LD_LIBRARY_PATH,可以看到它已经不再有效了(当然这不是使用参数“-Wl,-rpath”的必要步骤,在这里只是为了说明它已经不再起作用了),而且”pfoo”程序运行时也会发生找不到库的错误,而我们加入编译参数“-Wl,-rpath,./”之后得到的pfoo_r程序则能正常运行。
事实上我们可以通过readelf工具来查看两个文件的差异:
| # readelf -d pfoo
Dynamic segment at offset 0x514 contains 21 |
“readelf -d”可以用来查看ELF文件的动态节(Dynamic
Section)。对比pfoo 和pfoo_r的结果我们可以发现,pfoo_r中多出来了RPATH项,指定”Library rpath:
[./]”。通过这种方式,我们可以用非常小的代价(仅增加几乎可以忽略的空间开销),对每个ELF文件都指定最优化的搜索路径,达到提升性能的目的。这是我们比较推荐的一种方法。当然了,具体如果操作依赖于具体的软件系统的情况,简单的系统中直接将所有的库都放到/lib下也未尝不是一种简单易行的优化方案。
linux动态库加载时搜索路径的更多相关文章
- linux动态库加载RPATH, RUNPATH
摘自http://gotowqj.iteye.com/blog/1926771 linux动态库加载RPATH, RUNPATH 链接动态库 如何程序在连接时使用了共享库,就必须在运行的时候能够找到共 ...
- Linux 动态库加载
动态库运行时搜索顺序 1.LD_PRELOAD LD_PRELOAD是一个环境变量,用于动态库加载,动态库加载的优先级最高: 2.-wl,-rpath 编译目标代码时指定的动态库搜索路径(指的是用-w ...
- linux动态库加载的秘密
摘自http://gotowqj.iteye.com/blog/1926734 摘自http://www.360doc.com/content/14/0313/13/12747488_36024641 ...
- linux 动态库加载路径修改
1.在 /etc/ld.so.conf 文件中添加搜索路径,重启或者 ldconfig 生效: 2.在 /etc/ld.so.conf.d 目录下添加 *.conf 文件,其中可以添加搜索路径,重启获 ...
- linux动态库加载路径修改
1.在 /etc/ld.so.conf 文件中添加搜索路径,重启或者 ldconfig 生效: 2.在 /etc/ld.so.conf.d 目录下添加 *.conf 文件,其中可以添加搜索路径,重启获 ...
- 动态库加载时GetLasterror();值总是126的原因
1.dll路径不正确,导致找不到dll文件. 2.有可能是你要载入的DLL在内部还需要载入其它的dll,而它不存在,同样会返回126错误代码.比如一个你给系统添加了一个PCI设备,像AD采集卡之类的, ...
- linux和windows动态库加载路径区别
# linux和windows动态库加载路径区别 ### 简介------------------------------ linux加载动态库的路径是系统目录/lib和/usr/lib.- wind ...
- libdl.so 动态库加载、查找
使用libdl.so库 动态库加载原理 动态库中函数的查找已经封装成 libdl.so,有4个函数: dlopen : 打开一个动态库 dlsym : 在打开的动态库里找一个函数 dlclo ...
- 【转载】Linux下动态共享库加载时的搜索路径详解
转载自:http://www.eefocus.com/article/09-04/71617s.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading ...
随机推荐
- UESTC_冬马党 CDOJ 882
冬马党 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Statu ...
- LeeCode-Happy Number
Write an algorithm to determine if a number is "happy". A happy number is a number defined ...
- linux 有名管道(FIFO)
http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...
- Android 内部存储相关的函数(getCacheDir,getDir, getFileStreamPath,getFilesDir,openFileInput, ...)
为了保证应用程序存储数据的安全性,开发人员在开发应用程序的过程中须要注意使用Android 应用程序的内部存储空间. 依据不同的要求.将相应的数据文件.缓存文件.暂时文件等分别存储在相应的位置. 注意 ...
- tail
tail用于显示指定文件末尾内容,不指定文件时,作为输入信息进行处理.常用查看日志文件. -f 循环读取 -q 不显示处理信息 -v 显示详细的处理信息 -c<数目> 显示的字节数 -n& ...
- Activity之间通过intent 传递Map
//传递 Map<String,Object> data=orderlist.get(arg2-1); SerializableMap tmpmap=new SerializableMap ...
- Repeater动态添加行
<table class="table table-striped table-bordered table-hover"> <asp:Re ...
- JQ 复制节点
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Sql Server获得每个表的行数
SELECT o.[name], ddps.[row_count] FROM sys.indexes AS i INNER JOIN sys.objects AS o ON i.[object_id] ...
- HDU 5805 - NanoApe Loves Sequence (BestCoder Round #86)
先找相邻差值的最大,第二大,第三大 删去端点会减少一个值, 删去其余点会减少两个值,新增一个值,所以新增和现存的最大的值比较一下取最大即可 #include <iostream> #inc ...