对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“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 
     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 
     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: 
  Tag        Type                         Name/Value 
0x00000001 (NEEDED)                     Shared library: [libprint.so] 
0x00000001 (NEEDED)                     Shared library: [libc.so.6] 
0x0000000c (INIT)                       0x8048344 
0x0000000d (FINI)                       0x80484e0 
0x00000004 (HASH)                       0x8048128 
0x00000005 (STRTAB)                     0x8048240 
0x00000006 (SYMTAB)                     0x8048170 
0x0000000a (STRSZ)                      178 (bytes) 
0x0000000b (SYMENT)                     16 (bytes) 
0x00000015 (DEBUG)                      0x0 
0x00000003 (PLTGOT)                     0x80495f8 
0x00000002 (PLTRELSZ)                   16 (bytes) 
0x00000014 (PLTREL)                     REL 
0x00000017 (JMPREL)                     0x8048334 
0x00000011 (REL)                        0x804832c 
0x00000012 (RELSZ)                      8 (bytes) 
0x00000013 (RELENT)                     8 (bytes) 
0x6ffffffe (VERNEED)                    0x804830c 
0x6fffffff (VERNEEDNUM)                 1 
0x6ffffff0 (VERSYM)                     0x80482f2 
0x00000000 (NULL)                       0x0 
[root@localhost ldpath]# readelf -d pfoo_r 
Dynamic segment at offset 0x518 contains 22 entries: 
  Tag        Type                         Name/Value 
0x00000001 (NEEDED)                     Shared library: [libprint.so] 
0x00000001 (NEEDED)                     Shared library: [libc.so.6] 
0x0000000f (RPATH)                      Library rpath: [./] 
0x0000000c (INIT)                       0x8048348 
0x0000000d (FINI)                       0x80484e4 
0x00000004 (HASH)                       0x8048128 
0x00000005 (STRTAB)                     0x8048240 
0x00000006 (SYMTAB)                     0x8048170 
0x0000000a (STRSZ)                      181 (bytes) 
0x0000000b (SYMENT)                     16 (bytes) 
0x00000015 (DEBUG)                      0x0 
0x00000003 (PLTGOT)                     0x8049604 
0x00000002 (PLTRELSZ)                   16 (bytes) 
0x00000014 (PLTREL)                     REL 
0x00000017 (JMPREL)                     0x8048338 
0x00000011 (REL)                        0x8048330 
0x00000012 (RELSZ)                      8 (bytes) 
0x00000013 (RELENT)                     8 (bytes) 
0x6ffffffe (VERNEED)                    0x8048310 
0x6fffffff (VERNEEDNUM)                 1 
0x6ffffff0 (VERSYM)                     0x80482f6 
0x00000000 (NULL)                       0x0 
“readelf -d”可以用来查看ELF文件的动态节(Dynamic Section)。对比pfoo 和pfoo_r的结果我们可以发现,pfoo_r中多出来了RPATH项,指定”Library rpath: [./]”。通过这种方式,我们可以用非常小的代价(仅增加几乎可以忽略的空间开销),对每个ELF文件都指定最优化的搜索路径,达到提升性能的目的。这是我们比较推荐的一种方法。当然了,具体如果操作依赖于具体的软件系统的情况,简单的系统中直接将所有的库都放到/lib下也未尝不是一种简单易行的优化方案。

转载http://www.cnblogs.com/skyofbitbit/p/3688299.html

转载于:https://www.cnblogs.com/bigbear1385/p/6638249.html

Linux下动态共享库加载时的搜索路径详解相关推荐

  1. linux如何确定共享库路径,摘录Linux下动态共享库加载时的搜索路径详解

    对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似"error while loading shared libraries"这样的错误,这是典型的因为需要的动态库不在动态链接器 ...

  2. linux共享库的运行方式,Linux下动态共享库加载及使用详解

    对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似"error while loading shared libraries"这样的错误,这是典型的因为需要的动态库不在动态链接器 ...

  3. Linux下动态共享库加载及使用详解

    转载;http://blog.chinaunix.net/uid-29025972-id-3855500.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似"error whil ...

  4. [html] iOS下页面如何启动加载时显示画面图片?如何设置大小?它有什么好处?

    [html] iOS下页面如何启动加载时显示画面图片?如何设置大小?它有什么好处? <link rel="apple-touch-startup-image" href=&q ...

  5. python从date目录导入数据集_PyTorch加载自己的数据集实例详解

    数据预处理在解决深度学习问题的过程中,往往需要花费大量的时间和精力. 数据处理的质量对训练神经网络来说十分重要,良好的数据处理不仅会加速模型训练, 更会提高模型性能.为解决这一问题,PyTorch提供 ...

  6. Linux进程最大socket数,Linux下高并发socket最大连接数所受的各种限制(详解)

    1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每 ...

  7. linux修改zip中文件,Linux下修改jar、zip等文件内的文件详解

    Linux下修改jar.zip等文件内的文件详解 Linux下修改jar.zip等文件内的文件详解 看到很多同事在Linux环境下修改jar包内的文本文件或zip中的文本文件时,经常是先把jar包或z ...

  8. Linux下查看CPU型号,内存大小,硬盘空间的命令(详解)

    1 查看CPU 1.1 查看CPU个数*核心数 cat /proc/cpuinfo | grep "physical id" | uniq | wc -l 96 #一共96核 2 ...

  9. log4j加载配置方式和配置详解

    log4j配置详解 log4j的配置文件有两种格式分别是xml和properties.本文只讲解properties格式.比较properties简洁易懂. log4j加载配置文件方式 大家在刚接触l ...

最新文章

  1. 如何快速向数据库插1000万数据?4种方法对比,它简单却速度最快
  2. java成果_JAVA WEB期末项目第二阶段成果
  3. SAP Spartacus 数据类型定义汇总
  4. 2018.12.31 NOIP训练 czy的后宫5(树形dp)
  5. jvm性能调优工具之 jmap使用详解
  6. 安卓案例:View动画 - 弹球碰壁
  7. Python实现中英文混排时行号对齐
  8. mysql/mariadb主从复制
  9. 报头中的偏移量作用_网络中BN层的作用
  10. 真正开源erp,良心团队。点可云ERP
  11. 最新 PMP 考试真题概要及答案分析(中文版)(1)
  12. SAP WEB IDE local 安装
  13. 暗黑破坏神2中的符文系统,一共有多少个符文,可以介绍其中1个符文组合吗?...
  14. String 转表情, Swift 与 OC 中调用
  15. VuePress + GitHub Pages 生成静态网站
  16. oracle设置字符集为gbk,rac 环境下修改oracle数据库字符集为GBK
  17. 我用python分析买房数据
  18. 【SQL经典50题】9.查询和“ 01 “号的同学学习的课程完全相同的其他同学的信息【正解】
  19. kerberos认证相关概念和流程
  20. 中国可降解塑料行业深度分析及未来发展趋势展望2021年版

热门文章

  1. 查看 Android SDK Build-tools 版本号
  2. Oracle 通用查询:表、字段、表说明、所有用户、库版本
  3. 高性能MySQL(第3版)
  4. Day4-springmvc中文乱码处理和客户端跳转
  5. python wxpython backend wxagg_[宜配屋]听图阁
  6. mysql seq 重置_需要在Oracle中重置序列的值
  7. python以某种编码进行打印_如何在一场面试中展现你对Python的coding能力?
  8. 使用FindAncestor查找方式绑定且不需要使用datacontext
  9. 启动vm虚拟机里的系统时,提示此主机支持 AMD-V,但 AMD-V 处于禁用状态。
  10. 【Unity3D基础教程】给初学者看的Unity教程(四):通过制作Flappy Bird了解Native 2D中的RigidBody2D和Collider2D...