【转载】Linux下动态共享库加载时的搜索路径详解
转载自:http://www.eefocus.com/article/09-04/71617s.html
对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“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 entries: |
“readelf -d”可以用来查看ELF文件的动态节(Dynamic Section)。对比pfoo
和pfoo_r的结果我们可以发现,pfoo_r中多出来了RPATH项,指定”Library rpath:
[./]”。通过这种方式,我们可以用非常小的代价(仅增加几乎可以忽略的空间开销),对每个ELF文件都指定最优化的搜索路径,达到提升性能的目的。这
是我们比较推荐的一种方法。当然了,具体如果操作依赖于具体的软件系统的情况,简单的系统中直接将所有的库都放到/lib下也未尝不是一种简单易行的优化
方案。
【转载】Linux下动态共享库加载时的搜索路径详解的更多相关文章
- Linux下动态共享库加载时的搜索路径详解
对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading shared libraries”这样的错误,这是典型的因为需要的动态库不在动态链接器ld.so的搜索路径 ...
- <摘录>Linux下动态共享库加载时的搜索路径详解
对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading shared libraries”这样的错误,这是典型的因为需要的动态库不在动态链接器ld.so的搜索路径 ...
- Linux下动态共享库加载及使用详解
转载;http://blog.chinaunix.net/uid-29025972-id-3855500.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loa ...
- Linux下动态共享库加载及使用详解【转】
原文地址:http://blog.chinaunix.net/uid-29025972-id-3855500.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while l ...
- linux共享库加载
参考自: <<程序员的自我修养--链接.装载与库>> 第八章 Linux共享库的组织 以下截取部分内容 (这本书比较好的讲解了从程序的链接,装载,到运行) 共享库的兼容性 li ...
- phpcms加载系统类与加载应用类之区别详解
<?php 1. 加载系统类方法load_sys_class($classname, $path = ''", $initialize = 1)系统类文件所在的文件路径:/phpcms ...
- Linux下 ps -ef 和 ps aux 的区别及格式详解
原文:https://www.cnblogs.com/5201351/p/4206461.html Linux下ps -ef和ps aux的区别及格式详解 Linux下显示系统进程的命令ps,最常用的 ...
- Linux下高并发socket最大连接数所受的各种限制(详解)
1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每 ...
- linux动态库加载时搜索路径
摘自http://gotowqj.iteye.com/blog/1926613 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading shared librar ...
随机推荐
- lamper技能树
- python数据持久存储:pickle模块的使用
python的pickle模块实现了基本的数据序列和反序列化.通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储:通过pickle模块的反序列化操作,我们能够从文件 ...
- 那些在学习iOS开发前就应该知道的事(part 1)
英文原文:Things I wish I had known before starting iOS development—Part 1 http://www.cocoachina.com/ios/ ...
- 支付宝Wap支付你了解多少?
上几篇文章详细介绍了支付宝APP支付.微信APP支付 此文章来介绍下支付宝Wap支付(也叫作手机网站支付) 目录 1.创建应用并获取APPID 2.配置应用环境 3.配置沙箱环境 4.服务端实现(Ma ...
- android对象关系映射框架ormlite之一对多(OneToMany)
前两天,用ormlite对单张表进行了基本的操作,但是,我们知道通常情况对于单张表格进行操作在实际情况中很前两天不现实,那么ormlite能否像Hibenate那样实现多张表之间的一对多,多对多(即O ...
- android设置背景半透明效果
1.Button或者ImageButton的背景透明或者半透明 半透明:<Button android:background="#e0000000"···> 透明:&l ...
- adding validation annotators to model classes 在linq to EntityFrame的Model中添加前台验证validation annotators
The same solution can be applied for LINQ to SQL. The snippet the article shows for using the Metada ...
- 读Java 804 - Quick refresher
Upcast永远是成功的,但Downcast不是,记得做instanceof判断 仅抛不同异常,而返回值相同的重载是不可以的 static import只会import静态类 static metho ...
- 老鼠跑猫叫主人惊醒c++观察者模式实现
这个题目算是比较经典的观察者模式了,老鼠作为一个Subject,主动发出跑的动作,紧跟着猫由于老鼠的跑而发出叫声,主人也被惊醒,在这里猫跟主人都是被动的,是观察者角色,代码实现如下: class CS ...
- Linux设备驱动剖析之Input(三)
/* get current state of buttons */ ; i < pdata->nbuttons; i++) gpio_keys_report_event(&dda ...