【Linux】16. 动静态库

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自定义库的位置呢?

  1. 拷贝.so文件到系统共享库路径下, 一般指/usr/lib (安装 --> 现阶段不太推荐将自己写的安装到系统共享库中 )
  2. 添加到环境变量LD_LIBRARY_PATH当中(一次性)
    系统在搜索库文件路径时,除了在系统默认的库路径下查找之外还会在环境变量LD_LIBRARY_PATH当中查找
    在这里插入图片描述
    但是当我们将机器退出后,再运行又无法找到,原因是因为自定义的环境变量只在本次登录有效
  3. 配置/etc/ld.so.conf.d/,ldconfig更新
    在这里插入图片描述
  4. 给运行程序建立软链接
    在这里插入图片描述

5. 使用外部库

使用外部库
系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况
的函数(ncurses库)

#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

-lm表示要链接libm.so或者libm.a库文件

6. 动态库的加载

静态库是不会加载到内存当中的,在链接时静态库就是将其方法拷贝到对应的调用处,当后续程序在运行的过程当中就不再依赖静态库。
但是如果静态库当中的方法被不同的文件调用,会在内存中出现重复的代码(浪费空间)
链接时发生的拷贝会拷贝到虚拟地址空间的代码区当中,(程序在未编译形成之前,编译器也会按照虚拟地址空间的方式划分区域,对应的拷贝就是存放到代码区),所以未来这部分代码必须通过相对确定的地址位置来进行访问
在这里插入图片描述

动态库命令的理解:

  1. 为啥形成.o文件要带-fPIC选项 是因为会生成位置无关码,可以理解为形成的函数地址不是绝对编址,只是相对编址的方案
  2. -shell 打包形成动态库格式 ,方便操作系统以库方式加载

当内存中存在100个可执行程序,都使用的是同一个库的话,那么只需要将这一个库加载到内存当中即可(节约内存空间)

猜你喜欢

转载自blog.csdn.net/weixin_60915103/article/details/131314220