【Linux探索学习】第二十五弹——动静态库:Linux 中静态库与动态库的详细解析
Linux学习笔记:
https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482
前言:
在 Linux 系统中,静态库和动态库是开发中常见的两种库文件类型。它们在编译、链接、内存管理以及程序的性能和可维护性方面有着显著的差异。了解静态库与动态库的区别和使用方式,有助于开发者根据实际需求选择最适合的解决方案。本文将详细介绍静态库与动态库的概念、差异、使用方法,并通过实际的代码示例讲解如何创建和使用这些库。
目录
-
静态库与动态库的基本概念
- 静态库(Static Library)
- 动态库(Dynamic Library)
-
静态库与动态库的区别
- 编译与链接时机
- 文件格式与大小
- 性能与内存管理
- 使用场景
-
如何在 Linux 中创建静态库
- 创建静态库的步骤
- 静态库的使用示例
- 静态库的优缺点
-
如何在 Linux 中创建动态库
- 创建动态库的步骤
- 动态库的使用示例
- 动态库的优缺点
-
静态库与动态库的优缺点比较
- 性能方面
- 存储与内存使用
- 依赖管理
-
动态库的加载与链接机制
- 静态链接与动态链接的概念
- 动态库的查找机制
-
静态库与动态库的底层实现
- 静态库的实现机制
- 动态库的实现机制
-
进阶话题
- 如何处理库版本
- 库文件的符号表与重定位
- 库的跨平台使用
1. 静态库与动态库的基本概念
静态库(Static Library)
静态库是一种在编译时就将代码和资源打包到可执行文件中的库。静态库通常是由多个目标文件(.o 文件)组成的,最终在编译时会将这些目标文件的代码合并到程序的可执行文件中。静态库的扩展名通常为 .a。
静态库的特点:
- 在编译时将库文件的代码直接嵌入到可执行文件中。
- 每个程序都需要自己链接一份静态库的副本。
- 不需要在程序运行时进行额外的文件查找或加载。
- 编译过程中会把库的所有代码复制到目标文件中,增加了可执行文件的体积。
动态库(Dynamic Library)
动态库是一种在程序运行时加载的共享库。与静态库不同,动态库的代码不会在编译时直接嵌入到可执行文件中,而是在程序运行时通过动态链接器加载。动态库通常具有 .so(Shared Object)扩展名。
动态库的特点:
- 在程序运行时由操作系统动态加载。
- 可以被多个程序共享,减少了内存和磁盘空间的消耗。
- 不需要在编译时复制代码,程序的大小较小。
- 在程序运行时,可以更新动态库,而不需要重新编译所有依赖该库的程序。
2. 静态库与动态库的区别
| 特性 | 静态库(Static Library) | 动态库(Dynamic Library) |
|---|---|---|
| 文件扩展名 | .a | .so |
| 编译时机 | 在编译时静态链接 | 在运行时动态加载 |
| 链接方式 | 静态链接(编译时) | 动态链接(运行时) |
| 程序体积 | 较大,库的代码嵌入程序中 | 较小,库的代码不嵌入程序中 |
| 内存管理 | 每个程序都拥有库的副本 | 多个程序共享库的副本 |
| 依赖管理 | 依赖是固定的,程序与库紧耦合 | 依赖管理灵活,库的更新不需要重新编译 |
| 更新 | 更新需要重新编译所有依赖的程序 | 只需更新动态库,不需要重新编译程序 |
| 使用场景 | 不需要动态链接支持的独立应用 | 需要共享库、多程序共享资源的场景 |
编译与链接时机
- 静态库的链接发生在编译时。编译器会将库文件的所有目标文件内容复制到程序中,生成一个包含所有必要代码的可执行文件。
- 动态库的链接发生在程序运行时。动态链接器会在程序启动时加载所需的共享库,并将其中的符号解析并链接到程序中。
文件格式与大小
- 静态库通常是
.a格式,文件较大,因为它包含了库中所有的目标文件(.o文件)。- 动态库通常是
.so格式,文件较小,多个程序可以共享同一个动态库。
性能与内存管理
- 静态库的程序在运行时不需要加载额外的库文件,因为它们已经嵌入到可执行文件中,程序启动时性能较好。
- 动态库的程序在运行时需要加载外部库文件,虽然加载过程可能略有延迟,但多个程序可以共享同一个动态库,节省内存和磁盘空间。
使用场景
- 静态库适合小型应用程序和嵌入式系统,特别是当程序不依赖于大量外部库时。
- 动态库适合大型系统或需要频繁更新的应用程序,因为库更新不需要重新编译应用程序。
3. 如何在 Linux 中创建静态库
创建静态库的步骤
-
编写源代码: 创建一个简单的 C 文件,定义一些函数:
// mathlib.c #include <stdio.h>int add(int a, int b) {return a + b; }int subtract(int a, int b) {return a - b; } -
编译为目标文件: 使用
gcc将 C 文件编译为目标文件:gcc -c mathlib.c -o mathlib.o -
创建静态库: 使用
ar工具将目标文件打包成静态库:ar rcs libmath.a mathlib.o -
使用静态库: 创建一个程序来调用这个静态库:
// main.c #include <stdio.h>int add(int, int); int subtract(int, int);int main() {printf("Sum: %d\n", add(5, 3));printf("Difference: %d\n", subtract(5, 3));return 0; }编译并链接静态库:
gcc main.c -L. -lmath -o main -
运行程序:
./main
静态库的优缺点
优点:
- 不需要依赖外部库,程序独立性强。
- 程序启动速度较快。
缺点:
- 程序文件较大,内存占用较高。
- 如果库有更新,所有依赖该库的程序都需要重新编译。
4. 如何在 Linux 中创建动态库
创建动态库的步骤
-
编写源代码:
// mathlib.c #include <stdio.h>__attribute__((visibility("default"))) int add(int a, int b) {return a + b; }__attribute__((visibility("default"))) int subtract(int a, int b) {return a - b; } -
编译为共享库: 使用
gcc将代码编译为动态库:gcc -fPIC -shared mathlib.c -o libmath.so -
使用动态库: 创建一个主程序,调用动态库中的函数:
// main.c #include <stdio.h>int add(int, int); int subtract(int, int);int main() {printf("Sum: %d\n", add(5, 3));printf("Difference: %d\n", subtract(5, 3));return 0; }编译并链接动态库:
gcc main.c -L. -lmath -o main -
设置动态库路径并运行程序:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
动态库的优缺点
优点:
- 可以在程序运行时加载,多个程序共享同一个库。
- 更新库时无需重新编译依赖程序,降低了维护成本。
缺点:
- 程序启动时需要加载外部库,可能会稍慢。
- 如果程序依赖的库丢失或版本不兼容,可能会导致运行时错误。
5. 静态库与动态库的优缺点比较
| 特性 | 静态库 | 动态库 |
|---|---|---|
| 程序大小 | 较大,库的代码嵌入到程序中 | 较小,多个程序共享同一份库 |
| 内存使用 | 每个程序都需要加载一份库的副本 | 多个程序共享同一份库,节省内存 |
| 启动速度 | 较快,不需要加载外部库文件 | 稍慢,需要加载外部库文件 |
| 依赖管理 | 静态,程序与库紧密耦合 | 动态,程序可以独立于库更新 |
| 更新 | 需要重新编译所有依赖的程序 | 只需更新库文件,无需重新编译程序 |
6. 动态库的加载与链接机制
动态库的加载和链接分为两种方式:编译时动态链接(Compile-time Linking)和运行时动态链接(Runtime Linking)。
编译时动态链接
编译时动态链接指的是在编译时指定使用的动态库,编译器会将库的符号信息嵌入到可执行文件中。程序运行时,操作系统会加载对应的动态库。
运行时动态链接
运行时动态链接是指程序通过 dlopen() 等系统调用在运行时加载库文件。这种方式更为灵活,可以根据需要加载不同的库。
7. 静态库与动态库的底层实现
- 静态库:静态库文件实际上是一个归档文件,里面包含了一些目标文件(
.o文件)。当程序需要使用静态库时,链接器会从静态库中提取所需的目标文件,并将它们嵌入到可执行文件中。- 动态库:动态库文件是一个共享对象,包含了可以在多个程序中共享的代码。操作系统通过动态链接器(如 Linux 上的
ld.so)负责加载动态库并解析符号。
8. 进阶话题
如何处理库版本
库的版本管理对于动态库尤为重要。常见的方法是使用符号链接或者版本控制机制来管理不同版本的动态库。
库文件的符号表与重定位
库文件中的符号表包含了函数和变量的符号信息。链接器会根据符号表进行符号解析和重定位。
库的跨平台使用
动态库的跨平台使用通常依赖于编译时指定的架构和平台。使用如 autoconf、CMake 等工具可以帮助开发者更好地进行跨平台构建。
结论
静态库与动态库在 Linux 系统中的应用各有优势与劣势。静态库适用于需要独立性较强的程序,而动态库则适用于内存共享和版本更新更加灵活的场景。在实际开发中,开发者应根据应用的需求、维护成本和性能要求来选择合适的库类型。
本篇笔记:

感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!!
相关文章:
【Linux探索学习】第二十五弹——动静态库:Linux 中静态库与动态库的详细解析
Linux学习笔记: https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言: 在 Linux 系统中,静态库和动态库是开发中常见的两种库文件类型。它们在编译、链接、内存管理以及程序的性能和可维护性方面有着…...
远程和本地文件的互相同步
文章目录 1、rsync实现类似git push pull功能1. 基础概念2. 示例操作3. 定制化和进阶用法4. 定时同步(类似自动化) 2 命令简化1. 动态传参的脚本2. Shell 函数支持动态路径3. 结合环境变量和参数(更简洁)4. Makefile 支持动态路径…...
自然语言处理之jieba分词和TF-IDF分析
jieba分词和TF-IDF分析 目录 jieba分词和TF-IDF分析1 jieba1.1 简介1.2 终端下载1.3 基本语法 2 TF-IDF分析2.1 什么是语料库2.2 TF2.3 IDF2.4 TF-IDF2.5 函数导入2.6 方法 3 实际测试3.1 问题解析3.2 代码测试 1 jieba 1.1 简介 结巴分词(Jieba)是一个…...
探索式测试
探索式测试是一种软件测试风格,它强调独立测试人员的个人自由和职责,为了持续优化其工作的价值,将测试学习、测试设计、测试执行和测试结果分析作为相互支持的活动,在整个项目实现过程中并行地执行。 选择合适的探索式测试方法我…...
服务器数据恢复—raid5故障导致上层ORACLE无法启动的数据恢复案例
服务器数据恢复环境&故障: 一台服务器上的8块硬盘组建了一组raid5磁盘阵列。上层安装windows server操作系统,部署了oracle数据库。 raid5阵列中有2块硬盘的硬盘指示灯显示异常报警。服务器操作系统无法启动,ORACLE数据库也无法启动。 服…...
ISP各模块功能介绍
--------声明,本文为转载整理------- ISP各个模块功能介绍: 各模块前后效果对比: 黑电平补偿(BLC) 在理想情况下,没有光照射的像素点其响应值应为0。但是,由于杂质、受热等其它原因的影响&…...
Python 数据建模完整流程指南
在数据科学和机器学习中,建模是一个至关重要的过程。通过有效的数据建模,我们能够从原始数据中提取有用的洞察,并为预测或分类任务提供支持。在本篇博客中,我们将通过 Python 展示数据建模的完整流程,包括数据准备、建…...
深入学习RocketMQ
参考:RocketMQ从从入门到精通_rocketmq入门到精通-CSDN博客 1、消息的类型 普通消息 顺序消息 延时消息 批量消息 事务消息 2、在java中使用 2.1、pom.xml中加入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId…...
国产编辑器EverEdit - 扩展脚本:关闭所有未修改文档
1 扩展脚本:关闭所有未修改文档 1.1 应用场景 当用户打开过多文档时,部分文档已经修改,而大部分没有修改,为了减少在众多已打开文档中来回跳转的不便,可以将没有修改的文档全部关闭,但目前提供的快速关闭窗…...
数据结构二叉树-C语言
数据结构二叉树-C语言 1.树1.1树的概念与结构1.2树的相关术语1.3树的表示1.4树形结构实际运用场景 2.二叉树2.1概念与结构2.2特殊的二叉树2.2.1满二叉树2.2.2完全二叉树 2.3二叉树存储结构2.3.1顺序结构2.3.2链式结构 3.实现顺序结构的二叉树4.实现链式结构二叉树4.1前中后序遍…...
Python基于YOLOv8和OpenCV实现车道线和车辆检测
使用YOLOv8(You Only Look Once)和OpenCV实现车道线和车辆检测,目标是创建一个可以检测道路上的车道并识别车辆的系统,并估计它们与摄像头的距离。该项目结合了计算机视觉技术和深度学习物体检测。 1、系统主要功能 车道检测&am…...
代码随想录算法训练营第六十天|KM94.城市间货物运输Ⅰ|KM95.城市间货物运输Ⅱ|KM96.城市间货物运输Ⅲ
94. 城市间货物运输 I 2、Bellman_ford队列优化算法(又名SPFA) SPFA是对Bellman_ford算法的优化,由于Bellman_ford 算法 每次都是对所有边进行松弛,其实是多做了一些无用功。其实只需要对 上一次松弛的时候更新过的节点作为出发节…...
人工智能学习路线全链路解析
一、基础准备阶段(预计 2-3 个月) (一)数学知识巩固与深化 线性代数(约 1 个月): 矩阵基础:回顾矩阵的定义、表示方法、矩阵的基本运算(加法、减法、乘法)&…...
C++语言的学习路线
C语言的学习路线 C是一种强大的高级编程语言,广泛应用于系统软件、游戏开发、嵌入式系统和高性能应用等多个领域。由于其丰富的功能和灵活性,C是一门值得深入学习的语言。本文旨在为初学者制定一条系统的学习路线,帮助他们循序渐进地掌握C语…...
用于与多个数据库聊天的智能 SQL 代理问答和 RAG 系统(3) —— 基于 LangChain 框架的文档检索与问答功能以及RAG Tool的使用
介绍基于 LangChain 框架的文档检索与问答功能,目标是通过查询存储的向量数据库(VectorDB),为用户的问题检索相关内容,并生成自然语言的答案。以下是代码逻辑的详细解析: 代码结构与功能 初始化环境与加载…...
20250110doker学习记录
1.本机创建tts环境。用conda. 0.1安装。我都用的默认,你也可以。我安装过一次,如果修复,后面加 -u bash Anaconda3-2024.10-1-Linux-x86_64.sh等待一会。 (base) ktkt4028:~/Downloads$ conda -V conda 24.9.2学习资源 Conda 常用命令大…...
MPU6050: 卡尔曼滤波, 低通滤波
对于MPU6050(一种集成了三轴加速度计和三轴陀螺仪的惯性测量单元),对加速度值进行卡尔曼滤波,而对角速度进行低通滤波的选择是基于这两种传感器数据的不同特性和应用需求。以下是详细解释: 加速度值与卡尔曼滤波 为什么使用卡尔曼滤波? 噪声抑制: 加速度计信号通常包含…...
C++的标准和C++的编译版本
C的标准和C的编译版本:原理和概念 理解 C标准 和 C编译版本 的关系是学习 C 的一个重要部分。这两者虽然看似相关,但实际上分别涉及了不同的概念和技术。下面将通过层次清晰的解释,帮助新手理解这两个概念的差异、特点及其相互关系。 一、C标…...
python学习笔记—17—数据容器之字符串
1. 字符串 (1) 字符串能通过下标索引来获取其中的元素 (2) 旧字符串无法修改特定下标的元素 (3) index——查找字符串中任意元素在整个字符串中的起始位置(单个字符或字符串都可以) tmp_str "supercarrydoinb" tmp_position1 tmp_str.index("s") tmp_p…...
UE5 使用内置组件进行网格切割
UE引擎非常强大,直接内置了网格切割功能并封装为蓝图节点,这项功能在UE4中就存在,并且无需使用Chaos等模块。那么就来学习下如何使用内置组件实现网格切割。 1.配置测试用StaticMesh 对于被切割的模型,需要配置一些参数。以UE5…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
