1. 库概念的引出
但是如果只是单纯的将多个.o文件提供给使用者,那么如果.o文件过多链接就会变得非常复杂,于是我们考虑将所有的.o文件打包给使用者提供一个库文件即可。
库的本质就是.o文件的集合
2. 动静态库概念
在之前的学习过程中我们认识到动静态链接会生成对应的库类型
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
3. 静态库
3.1 静态库的生成
我们执行如下命令:
[hx@hx dynamic_static_lib]$ tar czf mylib.tgz mylib
[hx@hx dynamic_static_lib]$ ll
total 56
-rw-rw-r-- 1 hx hx 3296 Jun 22 13:03 libmymath.a
-rw-rw-r-- 1 hx hx 231 Jun 20 19:25 main.c
-rw-rw-r-- 1 hx hx 303 Jun 22 13:38 makefile
-rw-rw-r-- 1 hx hx 120 Jun 20 19:15 my_add.c
-rw-rw-r-- 1 hx hx 67 Jun 20 19:16 my_add.h
-rw-rw-r-- 1 hx hx 1544 Jun 22 13:03 my_add.o
drwxrwxr-x 4 hx hx 4096 Jun 22 13:39 mylib
-rw-rw-r-- 1 hx hx 940 Jun 22 14:46 mylib.tgz
-rwxrwxr-x 1 hx hx 8568 Jun 20 19:38 mymath
-rw-rw-r-- 1 hx hx 117 Jun 20 19:17 my_sub.c
-rw-rw-r-- 1 hx hx 64 Jun 20 19:17 my_sub.h
-rw-rw-r-- 1 hx hx 1544 Jun 22 13:03 my_sub.o
将库文件和头文件打包压缩,形成.tgz文件将其上传到yum资源当中或者发布到XXX网站上
使用者就可以通过访问网站/资源的方式来获取到
3.2 静态库的使用
3.2.1 指定当前路径下编译使用
那为啥不需要告诉编译器头文件需要链接哪个头文件,而是只是告诉编译器头文件路径即可,因为我们在代码编译时(#include "my_add.h")
已经告诉编译器了我们所要包含的头文件是啥了
==所以如果要链接第三方库,就一定要指明库的名称==
那为啥编写C语言/C++时,我们不需要指明库名称呢? -- 因为gcc(编译C语言) g++(编译C++) 编译器本身就知道链接库的名称
3.2.2 添加到系统路径下使用(安装)
这种方式其本质也叫做库的安装
软件的安装其实也是一个道理,将软件添加到对应的系统路径下
在学习的过程中不太推荐,因为目前编写的大多是测试/小程序没有经过严格的测试和发布这些流程,所以不推荐将自己写的库直接安装到系统当中
4. 动态库
4.1 动态库的生成
4.2 动态库的使用
==那么如何告诉OS自定义库的位置呢?==
- 拷贝.so文件到系统共享库路径下, 一般指/usr/lib (安装 --> 现阶段不太推荐将自己写的安装到系统共享库中 )
- 添加到环境变量LD_LIBRARY_PATH当中(一次性)
系统在搜索库文件路径时,除了在系统默认的库路径下查找之外还会在环境变量LD_LIBRARY_PATH当中查找
但是当我们将机器退出后,再运行又无法找到,原因是因为自定义的环境变量只在本次登录有效 - 配置/etc/ld.so.conf.d/,ldconfig更新
- 给运行程序建立软链接
5. 使用外部库
使用外部库
系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况
的函数(ncurses库)
-lm表示要链接libm.so或者libm.a库文件#include <math.h> #include <stdio.h> int main(void) { double x = pow(2.0, 3.0); printf("The cubed is %f\n", x); return 0; } gcc -Wall calc.c -o calc -lm
6. 动态库的加载
静态库是不会加载到内存当中的,在链接时静态库就是将其方法拷贝到对应的调用处,当后续程序在运行的过程当中就不再依赖静态库。
但是如果静态库当中的方法被不同的文件调用,会在内存中出现重复的代码(浪费空间)
链接时发生的拷贝会拷贝到虚拟地址空间的代码区当中,(程序在未编译形成之前,编译器也会按照虚拟地址空间的方式划分区域,对应的拷贝就是存放到代码区),所以未来这部分代码必须通过相对确定的地址位置来进行访问
动态库命令的理解:
- 为啥形成.o文件要带-fPIC选项 是因为会生成位置无关码,可以理解为形成的函数地址不是绝对编址,只是相对编址的方案
- -shell 打包形成动态库格式 ,方便操作系统以库方式加载
当内存中存在100个可执行程序,都使用的是同一个库的话,那么只需要将这一个库加载到内存当中即可(节约内存空间)