静态库和动态库
库的名字都是去掉lib和后缀之后的才是库名。这点很重要
静态库
静态库在linux下是.a文件。程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
系统角度:
静态库是在链接过程被加入到了进程地址空间的代码区。
图示:
好处:如果编译链接后,把静态库删掉也可以运行。这个程序具有可移植性。
坏处:让程序变得超级大,原因也很简单,就是因为加入了很多代码。
动态库
动态库在linux下是以.so结尾的文件。程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
动态库的链接是发生在程序运行的时候。共享区通过页表映射到物理内存里的动态库,这样就能直接使用了。
系统角度:
动态链接
-
由于动态库是运行的时候才去链接动态库的代码的,违反了我们之前的一贯认知,是先链接再运行。
因此我们一贯说的预处理编译汇编链接的链接是指把动态库代码从硬盘加载进内存的这个过程,被称为动态链接(dynamic linking) -
动态库的链接并不是外部整一个动态库的所有代码,而是程序需要什么函数,就链接对应函数。
-
动态库可以让多个进程使用
生成库
库的构成是头文件和库文件,其中库文件是.o文件
生成静态库
先给代码:
创建lib库代码:
执行静态库
步骤:
1.生成静态库首先要先生成.o文件。因此gcc -o选项即可
2.一堆.o文件不好看,帮他打包一下成一个文件。静态库打包用工具ar,选项是-rc(replace and create)
3.创建一个目录lib,里面放头文件和库文件。类似这样:
4.这个库就可以被链接使用了。程序要用这个静态库的时候,由于系统找不到这个库在哪,因此有以下几种方法帮助系统找到这个静态库。
第一种:选项
- 选项-I + 路径 ------- 用于找到头文件
- 选项-L + 路径 ------ 用于找到放.a文件的目录
- 选项-l + 文件名 ------ 用于找到需要的.a文件
第二种:加入系统指定的目录
/usr/lib
/usr/local/lib
生成动态库
先给代码
执行动态库代码:
先导入环境变量LD_LIBRARY_PATH = 动态库.so的路径
然后再执行。
否则就会报错:
为什么会这样呢?
这和动态库链接是在运行的时候链接有关系。
程序运行的时候,编译器gcc已经知道了这个库在哪里了,但是系统不知道。
问题来了:为什么系统要知道这个库在哪里?
原因是动态链接只是将动态库从硬盘加载进内存里面,然而系统还要帮助进程,让进程地址空间中的共享区通过页表映射到拥有动态库的内存。
因此导入环境变量的作用就是让系统找到动态库的位置,然后改变页表的映射关系,让程序找到动态库的位置。