个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创Linux系统基础-动态库和静态库
收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌
目录
1. 动静态库的概念
2. 生成静态库
3. 生成动态库
4. 使用静态库
5. 使用动态库
6. 使用外部库
7. 动态库加载
8. 总结
动态库与静态库的优缺点总结:
1. 静态库
2. 动态库
动态库和静态库使用场景总结:
1. 静态库的使用场景
2. 动态库的使用场景
1. 动静态库的概念
静态库(.a) : 程序在编译链接的时候把库的代码链接到可执行文件中, 程序运行的时候将不在需要静态库
动态库(.so) : 程序在运行的时候才去链接动态库的代码, 多个程序共享使用库的代码.
我们可以使用ldd查看一个程序所连接的库:
可以看到我们简单一个C语言程序连接了三个库
补充:
1. 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表, 而不是外部函数所在目标文件的整个机械码
2. 在可执行文件开始运动以前, 外部函数的机械码由操作系统从磁盘上的动态库中复制到内存中, 这个过程称为动态链接 (dynamic linking)
3. 动态库可以在多个程序间共享, 所以动态链接使得可执行文件更小, 节省了磁盘空间, 操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用, 节省了内存和磁盘空间
2. 生成静态库
测试程序:
add.h
#ifndef __ADD_H__
#define __ADD_H__
int add(int a, int b);
#endif // __ADD_H__
sub.h
#ifndef __SUB_H__
#define __SUB_H__
int sub(int a, int b);
#endif // __SUB_H__
add.c
#include "add.h"
int add(int a, int b)
{
return a + b;
}
sub.c
#include "add.h"
int sub(int a, int b)
{
return a - b;
}
main.c
#include <stdio.h>
#include "add.h"
#include "sub.h"
int main()
{
int a = 10;
int b = 20;
printf("add(%d, %d)=%d\n", a, b, add(a, b));
a = 100;
b = 20;
printf("sub(%d,%d)=%d\n", a, b, sub(a, b));
return 0;
}
直接运行结果:
生成静态库:
所谓的库文件, 本质, 就是把.o打包
ar是gnu归档工具,rc表示(replace and create)
查看静态库中的目录列表, t:列出静态库中的文件 v:verbose 详细信息
3. 生成动态库
shared: 表示生成共享库格式
fPIC:产生位置无关码(position independent code)
库名规则:libxxx.so
4. 使用静态库
-L 指定库路径 -l 指定库名
测试目标文件生成后,静态库删掉,程序照样可以运行
库搜索路径 :
从左到右搜索-L指定的目录.
由环境变量指定的目录 (LIBRARY_PATH)
由系统指定的目录
1. /usr/lib
2. /usr/lical/lib
5. 使用动态库
编译选项:
l:链接动态库,只要库名即可(去掉lib以及版本号)
L:链接库所在的路径
6. 使用外部库
系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况的函数(ncurses库)
下载ncurses库
sudo apt update
sudo apt install libncurses5-dev libncursesw5-dev
示例代码:
#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;
}
-lm表示要链接libm.so或者libm.a库文件
库文件名称和引入库的名称
如:libc.so -> c库,去掉前缀lib,去掉后缀.so,.a
7. 动态库加载
动态库在加载之后, 要映射在当前进程的堆栈之间的共享区
动态库也叫做共享库!!
8. 总结
动态库要在程序运行的时候, 要找到动态库加载并运行!
静态库为什么没有这个问题? 因为静态库编译期间已经将库中的代码拷贝到我们的可执行文件内部了, 加载和库就没有关系了~
动态库 VS 静态库
默认连接的是动态库, 如果你没有使用-static, 并且只提供.a, 只能静态链接当前的.a库, 其他库正常动态链接
-static的意义是什么呢? 必须强制将我们的程序静态连接, 这就要求我们来凝结的任何库都必须提供对应的静态库版本~~
动态库与静态库的优缺点总结:
1. 静态库
优先:
1. 执行效率高 : 静态库在编译时直接连接到可执行文件中, 因此程序在运行时不需要加载库文件, 通常会有更快的启动时间和执行效率.
2. 部署简单: 将所有代码打包为一个可执行文件, 不需要在运行时依赖外部库, 简化了部署过程
3. 版本控制: 不受外部库版本的影响, 避免了库更新造成的问题
缺点:
1. 文件大小大: (上文也有所展示)因为将库的代码复制到每个可执行文件中, 导致生成的可执行文件体积较大, 占用很大内存
2. 更新困难 : 如果需要修复静态库中的bug或添加新特性, 需要重新编译有所依赖该库的可执行文件
3. 资源浪费 : 如果多个程序使用相同的静态库, 它们会各自包含一份库的副本, 占用更多的磁盘和内存空间
2. 动态库
优先:
1. 节省内存 : 多个进程可以共享同一个动态库的副本, 减少了内存使用
2. 更新方便 : 只需要替换动态库文件, 无需重新编译依赖该库的应用程序, 便于维护和更新
3. 启动速度快 : 可以在程序运行时按需加载库, 减少初始加载时间
缺点:
1. 运行时依赖 : 程序运行时需要依赖动态库, 缺失动态库会导致程序无法运行.
2. 调试复杂 : 由于动态连接, 调试过程可能会更加复杂, 特别是在库的版本不兼容时.
3. 加载开销 : 动态库在运行时需要加载, 可能会导致启动时间延长
动态库和静态库使用场景总结:
1. 静态库的使用场景
1. 小型项目 : 对于小型项目或工具, 使用静态库可以简化构建和部署流程.
2. 不频繁更新的库 : 当库功能稳定且不需要频繁更新时, 使用静态库是合法的
3. 性能要求高的应用 : 在对性能有严格要求的场景下, 静态库可能更具有优势
2. 动态库的使用场景
1.大型应用程序 : 在大型系统中, 使用动态库可以减少内存占用, 特别是当多个程序共享一个库时
2. 频繁更新的库 : 当库需要频繁更新, 且不希望重新编译所有应用时, 动态库是更好的选择.
3. 插件系统 : 在需要实现插件架构的应用中, 动态库允许程序在运行时加载和卸载插件
4. 跨平台开发 : 动态库在不同平台上的使用可以更灵活, 特别是在使用不同版本的依赖时.