转载;http://blog.chinaunix.net/uid-29025972-id-3855500.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:

  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)                     0x8049*

  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下也未尝不是一种简单易行的优化 方案。

Linux下动态共享库加载及使用详解的更多相关文章

  1. Linux下动态共享库加载及使用详解【转】

    原文地址:http://blog.chinaunix.net/uid-29025972-id-3855500.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while l ...

  2. 【转载】Linux下动态共享库加载时的搜索路径详解

    转载自:http://www.eefocus.com/article/09-04/71617s.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while loading ...

  3. Linux下动态共享库加载时的搜索路径详解

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

  4. <摘录>Linux下动态共享库加载时的搜索路径详解

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

  5. linux共享库加载

    参考自: <<程序员的自我修养--链接.装载与库>> 第八章 Linux共享库的组织 以下截取部分内容 (这本书比较好的讲解了从程序的链接,装载,到运行) 共享库的兼容性 li ...

  6. (转)Linux下select, poll和epoll IO模型的详解

    Linux下select, poll和epoll IO模型的详解 原文:http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll ...

  7. 转: javascript模块加载框架seajs详解

    javascript模块加载框架seajs详解 SeaJS是一个遵循commonJS规范的javascript模块加载框架,可以实现javascript的模块化开发和模块化加载(模块可按需加载或全部加 ...

  8. seo网页加速技术,预加载 DNS Prefetching 详解

    seo网页加速技术,预加载 DNS Prefetching 详解 DNS Prefetching 是什么 : DNS 是什么-- Domain Name System,域名系统,作为域名和IP地址相互 ...

  9. (总结)Linux下的暴力密码在线破解工具Hydra详解

    (总结)Linux下的暴力密码在线破解工具Hydra详解 学习了:https://blog.csdn.net/yafeichang/article/details/53502869

随机推荐

  1. javascript当中的this详解

    总结this的3个规则: this是调用上下文,上下文被创建或者初始化时才确定 非严格模式:this是全局对象:严格模式:this是undefined 函数调用 a. 以函数形式调用的函数通常不使用t ...

  2. CVE-2012-0158个人分析

    CVE-2012-0158是一个比较有名的老漏洞了,这次从论坛上找到一个poc文件,利用这个poc来分析CVE-2012-0158漏洞的形成. http://bbs.pediy.com/showthr ...

  3. Linux shell 中$() ` `,${},$[] $(()),[ ] (( )) [[ ]]作用与区别

    转载自 https://blog.csdn.net/x1269778817/article/details/46535729 参考: https://stackoverflow.com/questio ...

  4. oracle语句练习

    1.查看该公司的员工分布在哪几个部门 select distinct deptno from emp; 2.查看每个部门有哪些岗位 select distinct deptno , job from ...

  5. win7下docker环境centos容器中安装mysql5.7

    docker环境基于镜像skiychan/nginx-php7,进行安装 ps:skiychan/nginx-php7此镜像已封装nginx1.15.3+php7.2.9 1.环境配置 配置共享文件夹 ...

  6. Django Suit v2-dev 使用

    转:链接:https://www.jianshu.com/p/84fa8219fb48 官方文档: 链接 Git: 链接 install Django Suit 为了适配 Django 有许多不同的版 ...

  7. 浅谈三款常用软件 - Chrome、Intellij IDEA、Cygwin

    作为一个每天的接触计算机的程序员,肯定也会接触形形色色的软件,不过今天在此介绍的三款软件,则是我每天都要用到的,而且我认为它们非常好用,极大的提高了我的开发效率. 1.Chrome Google的大名 ...

  8. LibreOJ#143 质数判定 [Miller_Rabin]

    题目传送门 质数判定 题目描述 判定输入的数是不是质数. 输入格式 若干行,一行一个数 x. 行数不超过 $1.5\times 10^4$ 输出格式 对于输入的每一行,如果 x是质数输出一行 Y,否则 ...

  9. 【HDU 6020】 MG loves apple (乱搞?)

    MG loves apple  Accepts: 20  Submissions: 693  Time Limit: 3000/1500 MS (Java/Others)  Memory Limit: ...

  10. 【UOJ #107】【APIO 2013】ROBOTS

    http://uoj.ac/problem/107 设\(f(l,r,i,j)\)表示\([l,r]\)中的机器人聚集到\((i,j)\)需要花的最小操作数. \(f(l,r,i,j)=\min\le ...