β

静态库和动态库

ASPIRE 8 阅读

=Start=

缘由:

补充系统知识

正文:

参考解答:

我们通常把一些公用函数制作成函数库,供其它程序使用(代码的复用)。函数库可分为静态库和动态库两种:

动态库和静态库二者的不同点在于代码被载入的时刻不同。

静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大。动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。

静态情况下,把库直接加载到程序中,而动态库链接的时候,它只是保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度,和降低程序的耦合度。

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

1.什么是库?

在Windows平台和Linux平台下都大量存在着库。从本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。由于Windows和Linux的本质不同,因此二者库的二进制是不兼容的。本文仅限于介绍Linux下的库。

2.库的种类

Linux下的库有两种:静态库和动态库(共享库)。二者的不同点在于代码被载入的时刻不同。

3.库存在的意义

库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。

现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。

4.在Linux下如何生成库文件?

Linux下静态库的后缀是.a,它的产生分两步:

Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表;

Step 2.用ar命令将很多.o转换成.a,成为静态库;

Linux下动态库的后缀是.so,它由gcc加特定参数编译产生。

例如:
$ gcc -fPIC -c *.c

$ gcc -shared -Wl,-soname, libfoo.so.1 -olibfoo.so.1.0 *.

5.库文件是如何命名的,有没有什么规范?

在Linux下,库文件一般放在/usr/lib和/lib下(64位系统对应的是/usr/lib64和/lib64):

6.如何知道一个可执行程序依赖哪些库

ldd命令可以查看一个可执行程序依赖的共享库,例如:

# ldd /bin/ln

libc.so.6 => /lib/libc.so.6 (0×40021000)

ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)

可以看到ln命令依赖于libc库和ld-linux库。

7.可执行程序在执行的时候如何定位共享库文件?

当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。

此时就需要系统动态载入器(dynamiclinker/loader),对于elf格式的可执行程序,是由ld-linux.so*来完成的。

它先后搜索elf文件的DT_RPATH段,环境变量LD_LIBRARY_PATH,/etc/ld.so.cache文件列表,/lib/,/usr/lib目录,找到库文件后将其载入内存。

  1. (仅ELF文件)使用可执行文件中DT_RPATH区域设置的属性,如果DT_RUNPATH被设置,那么忽略DT_RPATH(在我的Linux对应的是RPATH和RUNPATH);
  2. 使用环境变量LD_LIBRARY_PATH,如果可执行文件中有 set-user-id/set-group-id 会被忽略;
  3. (仅ELF文件)使用可执行文件中DT_RUNPATH区域设置的属性;
  4. 从/etc/ld.so.cache缓存文件中查找;
  5. 从默认路径/lib、/usr/lib文件目录中查找。
8.在新安装一个库之后如何让系统能够找到它?

如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:

1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径。

2.运行ldconfig,该命令会重建/etc/ld.so.cache文件。

参考链接:

=END=

作者:ASPIRE
Read more, write more, know more.
原文地址:静态库和动态库, 感谢原作者分享。

发表评论