`

linux动态库加载时搜索路径

阅读更多
 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“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> 

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> 

3 extern void print_foo(); 

5 int main() 
6 { 
7 print_foo(); 

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

   
分享到:
评论

相关推荐

    linux 动态库静态库

    通过压缩包中的"linux动态库及静态库的创建和使用"文件,你可以找到更具体的实践教程和示例代码,包括如何创建、链接和使用这两种类型的库,以及解决可能出现的问题。这些资料将帮助你深入理解和掌握Linux环境下的...

    linux动态库的生成与使用

    在 Linux 系统中,动态库的搜索路径可以通过多种方式指定: * 使用 `-L` 选项指定编译时的库路径,例如: ``` gcc main.c -o main -L ./ -lcac ``` * 使用 `LD_PRELOAD` 环境变量指定运行时的库路径,例如: ``` LD...

    Windows和Linux动态库

    Linux动态库的工作原理类似,但其加载和管理机制略有不同。动态库的加载由ld.so动态链接器处理,可以通过ldd命令查看程序依赖的库。Linux下,动态库的调用也是静态和动态两种方式: - 静态调用:编译时通过-L和-l...

    Linux下qt动态库创建和使用

    - 在使用动态库的项目中添加库路径和链接选项。 - 正确包含头文件并使用库中的接口。 通过以上步骤,你可以有效地在Linux下利用Qt进行动态库的开发和应用。这对于模块化编程和代码复用至关重要,特别是在大型软件...

    Linux qtcreator动态加载动态链接库案例

    创建一个新的Qt Console Application项目,然后在项目构建设置中确保链接器参数正确配置,指向我们的动态库。这通常通过在.pro文件中添加以下行来完成: ```pro LIBS += -L/path/to/library -lmylib ``` 这里的`-L...

    linux动态库生成

    总结,生成Linux动态库是通过C语言编程实现的,涉及的关键操作包括编译源代码为对象文件,使用`-shared`选项创建动态库,安装库到系统路径,并更新链接器缓存。正确使用动态库能够提高软件开发的效率和质量。

    Linux动态库搜索路径(目录)设置

    今天编译完程序运行的时候,报一个错误,说库文件不存在,然后我看了一下,程序的当前路径下就有这个库文件,我以前...众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib。动态库被创建后,一般都复制到这两个目录中。当

    Linux动态库连接

    在本资料中,我们将深入探讨Linux动态库连接的概念、工作原理以及如何在Qt开发环境中使用动态库。 1. **动态库的类型** - `.so` 文件:这是Linux下动态库的标准格式,全称为"Shared Object"。例如,`libmylib.so` ...

    linux动态链接库的开发实例

    Linux系统支持延迟加载动态链接库,即直到调用库中的某个函数时才会真正加载库。这样可以提高程序启动速度,因为不是所有库都会在程序启动时立即使用。 六、版本管理 动态链接库可以通过版本号来管理,如`libmylib....

    Linux下动态链接库加载路径及搜索路径问题

    总之,理解Linux下的动态链接库加载路径和搜索路径对于解决程序运行时的“error while loading shared libraries”这类问题至关重要。正确配置这些路径可以确保程序能够顺利运行,并有效管理系统的资源。在日常操作...

    linux_dongtai_lib.zip_linux 动态库

    通过学习和实践“linux_dongtai_lib.zip”中的内容,开发者可以熟练掌握Linux动态库的创建、链接和管理,提升程序开发的效率和灵活性。动态库技术在大型软件项目中尤其重要,因为它允许模块化开发,降低代码冗余,...

    LINUX下生成动态库.doc

    "Linux动态库生成和使用" 一、动态库的概念和优点 动态库是一种共享库,允许多个应用程序共享同一个库文件,减少了内存占用和磁盘空间占用。动态库的优点包括:减少内存占用、提高程序执行速度、简化程序开发和...

    kafka linux C++ 动态库

    5. **运行程序**:编译完成后,确保运行环境也已经配置了动态库的搜索路径,通常是通过`LD_LIBRARY_PATH`环境变量或者`/etc/ld.so.conf`配置文件来实现。 6. **错误处理**:在使用过程中,要注意处理可能出现的网络...

    linux应用程序启动动态库加载问题.docx

    总之,理解Linux动态库加载机制对于排查这类问题至关重要。通过仔细分析库的搜索路径、加载过程和重定位步骤,我们可以定位问题并找到解决方案。在实际操作中,应结合`ldd`、`readelf`、`strace`和`ldconfig`等工具...

    Linux下C++动态库

    在Linux系统中,C++动态库(也称为共享对象或.so文件)是程序运行时可以加载和使用的代码库。它们允许多个程序共享同一份代码,从而节省内存并简化软件维护。下面将详细介绍如何创建、使用和管理Linux下的C++动态库...

    LINUX动态库.so嵌套.so文件

    总之,Linux动态库的嵌套使用是一项高级技术,它允许我们在设计复杂系统时更好地组织代码,实现模块化,并通过共享库来提高效率。通过深入理解和实践这些知识点,开发者可以创建更高效、可维护的软件系统。在实际...

    Linux静态库和动态库的制作和使用(ubuntu18.04)以及解决动态库加载失败问题

    本文将详细介绍如何在Ubuntu 18.04上制作和使用这两种类型的库,以及如何解决动态库加载失败的问题。 首先,让我们了解一下静态库(.a文件)。静态库是将所有对象文件合并成一个单一文件,当编译程序时,链接器会将...

    linux动态链接库示例

    总结来说,"linux动态链接库示例"是一个关于如何在Linux环境下使用C语言创建、编译和使用动态链接库(`.so`文件)的过程。通过理解这些步骤,开发者能够更好地管理和利用系统资源,提高软件的复用性和维护性。

    boost库1.68版本Linux下编译的动态库和静态库

    6. **使用编译好的库**:在项目中使用编译的Boost库时,需要链接对应的动态库(如`-lboost_thread -lboost_system`)或者静态库,并确保库的路径被系统搜索路径(`LD_LIBRARY_PATH`或`DYLD_LIBRARY_PATH`)包含。...

    linux qt 动态链接库

    6. **调试动态链接问题**:使用`strace`工具可以跟踪系统调用,帮助找出程序在尝试加载动态库时的问题。 7. **静态链接与动态链接的权衡**:虽然静态链接可以避免上述的一些问题,但会增加程序大小且不利于库的更新...

Global site tag (gtag.js) - Google Analytics