动态链接库 学习笔记(一)理论知识

一、概念

静态链接:对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下,所以这些函数库被成为静态库(static libaray),通常文件名为“libxxx.a”的形式。

动态链接:把对一些库函数的链接载入推迟到程序运行的时期(runtime)。这就是动态链接库(dynamic link library)技术,动态链接库文件名为“libxxxx.so”的形式。(so有可能是shared object的缩写)

二、优势

1. 程序体积缩小

      多个程序可能存在公共的代码逻辑,这些代码逻辑可以抽成公共共享库,多个程序允许时直接使用这些公共库,避免重复开发,同时也可以减少程序体积;

2. 可以实现进程之间的资源共享。

     什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。

3. 将一些程序升级变得简单。

     用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。

4. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。

      程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。

三、案例

1、加入 动态链接库 到系统默认库中

     linux 系统中存在如下目录或文件

  • ld.so.cache

          该文件包含了当前系统中所有 在库路径中找到的编译好的候选库列表,需要动态链接的可执行程序在运行的时候,系统的动态链接器 (dynamic loader)会从该文件中查找其需要链接的动态共享库。

          该文件的内容来源于 ld.so.conf ,每次执行 ldconfig 命令时,都会刷新 ld.so.cache 文件,将 ld.so.conf 文件动态链接的搜索路径及其下的动态路径库写入该文件中。

  • ld.so.conf

          记录系统中的动态链接共享库存放路径,默认包含:/lib,/usr/lib,/usr/lib64,如果有其它的动态链接共享库存放路径可追加到该文件中,但是每次追加完毕之后,都需要执行ldconfig命令,使其生效到 ld.so.cache 文件中

          该文件中的内容如下:       

include ld.so.conf.d/*.conf
/usr/lib64

   可以看到 ld.so.conf 文件 通过 include 方式 将 ld.so.conf.d 目录下 所有 conf 文件中的搜索路径全部包含进来了,这么做有一个好处,所有的动态链接共享库的路径不需要在一个文件中全部写完造成文件体积变大,同时可以 ld.so.conf.d 子目录的形式分类存放 动态链接共享库。

  • ld.so.conf.d

2、程序运行时指定 动态链接库 搜索路径

      系统通过 ld.so.conf 文件记录了所有可加载的动态链接库的路径,但是由于所有系统中运行的所有程序需要的动态链接库都是从这里搜索路径加载的,可能会出现一个问题,程序本身需要的动态链接库版本高于 ld.so.conf 登记的路径下的版本,此时也不能随便升级 登记的路径下的动态链接库的版本。

      基于此,一般做法是 程序自带了 so 库,在程序运行的时候 通过  export  LD_LIBRARY_PATH 指定先搜索自带的动态链接库,当满足不了的时候,再从 ld.so.conf 文件中登记的路径下搜索动态链接库。 即:

       要指示动态装入器首先检查某个目录,请将 LD_LIBRARY_PATH 变量设置成您希望搜索的目录。多个路径之间用冒号分隔;例如:

  # export LD_LIBRARY_PATH="/usr/lib/old:/opt/lib"

  导出 LD_LIBRARY_PATH 后,如有可能,所有从当前 shell 启动的可执行程序都将使用 /usr/lib/old 或 /opt/lib 中的库,如果仍不能满足一些共享库相关性要求,则转回到 /etc/ld.so.conf 中指定的库。

      一般情况下,不会将自己带的动态链接库直接配置到系统文件ld.so.conf,否则会污染系统库,造成服务器中其它依赖系统动态链接库出现问题。基于此,自带的动态链接库可以在自己程序使用之前使用 export方式让其优先查找自带动态链接库的路径,如:export LD_LIBRARY_PATH=<自己路径>:$LD_LIBRARY_PATH, export 是临时生效的。

 3、查看 可执行的二进制程序  在当前操作系统中运行的话 是否缺失依赖的动态链接库  

     ldd   xxxx  (ldd 命令列出其依赖的所有 动态链接库,如当前系统中缺失,列表中会有关键字进行指出)

如:

 

 

 

 

 

 

参考资料:

https://www.cnblogs.com/wangnengwu/p/7760606.html

http://blog.chinaunix.net/uid-25304914-id-3046279.html

 

posted @ 2022-02-13 15:28  夏之夜  阅读(130)  评论(0编辑  收藏  举报