当前位置: 首页 > news >正文

【Linux探索学习】第二十五弹——动静态库:Linux 中静态库与动态库的详细解析

Linux学习笔记:

https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482

前言:

在 Linux 系统中,静态库和动态库是开发中常见的两种库文件类型。它们在编译、链接、内存管理以及程序的性能和可维护性方面有着显著的差异。了解静态库与动态库的区别和使用方式,有助于开发者根据实际需求选择最适合的解决方案。本文将详细介绍静态库与动态库的概念、差异、使用方法,并通过实际的代码示例讲解如何创建和使用这些库。

目录

  1. 静态库与动态库的基本概念

    • 静态库(Static Library)
    • 动态库(Dynamic Library)
  2. 静态库与动态库的区别

    • 编译与链接时机
    • 文件格式与大小
    • 性能与内存管理
    • 使用场景
  3. 如何在 Linux 中创建静态库

    • 创建静态库的步骤
    • 静态库的使用示例
    • 静态库的优缺点
  4. 如何在 Linux 中创建动态库

    • 创建动态库的步骤
    • 动态库的使用示例
    • 动态库的优缺点
  5. 静态库与动态库的优缺点比较

    • 性能方面
    • 存储与内存使用
    • 依赖管理
  6. 动态库的加载与链接机制

    • 静态链接与动态链接的概念
    • 动态库的查找机制
  7. 静态库与动态库的底层实现

    • 静态库的实现机制
    • 动态库的实现机制
  8. 进阶话题

    • 如何处理库版本
    • 库文件的符号表与重定位
    • 库的跨平台使用

1. 静态库与动态库的基本概念

静态库(Static Library)

静态库是一种在编译时就将代码和资源打包到可执行文件中的库。静态库通常是由多个目标文件(.o 文件)组成的,最终在编译时会将这些目标文件的代码合并到程序的可执行文件中。静态库的扩展名通常为 .a

静态库的特点

  • 在编译时将库文件的代码直接嵌入到可执行文件中。
  • 每个程序都需要自己链接一份静态库的副本。
  • 不需要在程序运行时进行额外的文件查找或加载。
  • 编译过程中会把库的所有代码复制到目标文件中,增加了可执行文件的体积。
动态库(Dynamic Library)

动态库是一种在程序运行时加载的共享库。与静态库不同,动态库的代码不会在编译时直接嵌入到可执行文件中,而是在程序运行时通过动态链接器加载。动态库通常具有 .so(Shared Object)扩展名。

动态库的特点

  • 在程序运行时由操作系统动态加载。
  • 可以被多个程序共享,减少了内存和磁盘空间的消耗。
  • 不需要在编译时复制代码,程序的大小较小。
  • 在程序运行时,可以更新动态库,而不需要重新编译所有依赖该库的程序。

2. 静态库与动态库的区别

特性静态库(Static Library)动态库(Dynamic Library)
文件扩展名.a.so
编译时机在编译时静态链接在运行时动态加载
链接方式静态链接(编译时)动态链接(运行时)
程序体积较大,库的代码嵌入程序中较小,库的代码不嵌入程序中
内存管理每个程序都拥有库的副本多个程序共享库的副本
依赖管理依赖是固定的,程序与库紧耦合依赖管理灵活,库的更新不需要重新编译
更新更新需要重新编译所有依赖的程序只需更新动态库,不需要重新编译程序
使用场景不需要动态链接支持的独立应用需要共享库、多程序共享资源的场景
编译与链接时机
  • 静态库的链接发生在编译时。编译器会将库文件的所有目标文件内容复制到程序中,生成一个包含所有必要代码的可执行文件。
  • 动态库的链接发生在程序运行时。动态链接器会在程序启动时加载所需的共享库,并将其中的符号解析并链接到程序中。
文件格式与大小
  • 静态库通常是 .a 格式,文件较大,因为它包含了库中所有的目标文件(.o 文件)。
  • 动态库通常是 .so 格式,文件较小,多个程序可以共享同一个动态库。
性能与内存管理
  • 静态库的程序在运行时不需要加载额外的库文件,因为它们已经嵌入到可执行文件中,程序启动时性能较好。
  • 动态库的程序在运行时需要加载外部库文件,虽然加载过程可能略有延迟,但多个程序可以共享同一个动态库,节省内存和磁盘空间。
使用场景
  • 静态库适合小型应用程序和嵌入式系统,特别是当程序不依赖于大量外部库时。
  • 动态库适合大型系统或需要频繁更新的应用程序,因为库更新不需要重新编译应用程序。

3. 如何在 Linux 中创建静态库

创建静态库的步骤
  1. 编写源代码: 创建一个简单的 C 文件,定义一些函数:

    // mathlib.c
    #include <stdio.h>int add(int a, int b) {return a + b;
    }int subtract(int a, int b) {return a - b;
    }
    
  2. 编译为目标文件: 使用 gcc 将 C 文件编译为目标文件:

    gcc -c mathlib.c -o mathlib.o
    
  3. 创建静态库: 使用 ar 工具将目标文件打包成静态库:

    ar rcs libmath.a mathlib.o
    
  4. 使用静态库: 创建一个程序来调用这个静态库:

    // 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
    
  5. 运行程序

    ./main
    
静态库的优缺点

优点

  • 不需要依赖外部库,程序独立性强。
  • 程序启动速度较快。

缺点

  • 程序文件较大,内存占用较高。
  • 如果库有更新,所有依赖该库的程序都需要重新编译。

4. 如何在 Linux 中创建动态库

创建动态库的步骤
  1. 编写源代码

    // 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;
    }
    
  2. 编译为共享库: 使用 gcc 将代码编译为动态库:

    gcc -fPIC -shared mathlib.c -o libmath.so
    
  3. 使用动态库: 创建一个主程序,调用动态库中的函数:

    // 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
    
  4. 设置动态库路径并运行程序

    export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
    ./main
    
动态库的优缺点

优点

  • 可以在程序运行时加载,多个程序共享同一个库。
  • 更新库时无需重新编译依赖程序,降低了维护成本。

缺点

  • 程序启动时需要加载外部库,可能会稍慢。
  • 如果程序依赖的库丢失或版本不兼容,可能会导致运行时错误。

5. 静态库与动态库的优缺点比较

特性静态库动态库
程序大小较大,库的代码嵌入到程序中较小,多个程序共享同一份库
内存使用每个程序都需要加载一份库的副本多个程序共享同一份库,节省内存
启动速度较快,不需要加载外部库文件稍慢,需要加载外部库文件
依赖管理静态,程序与库紧密耦合动态,程序可以独立于库更新
更新需要重新编译所有依赖的程序只需更新库文件,无需重新编译程序

6. 动态库的加载与链接机制

动态库的加载和链接分为两种方式:编译时动态链接(Compile-time Linking)和运行时动态链接(Runtime Linking)。

编译时动态链接

编译时动态链接指的是在编译时指定使用的动态库,编译器会将库的符号信息嵌入到可执行文件中。程序运行时,操作系统会加载对应的动态库。

运行时动态链接

运行时动态链接是指程序通过 dlopen() 等系统调用在运行时加载库文件。这种方式更为灵活,可以根据需要加载不同的库。

7. 静态库与动态库的底层实现

  • 静态库:静态库文件实际上是一个归档文件,里面包含了一些目标文件(.o 文件)。当程序需要使用静态库时,链接器会从静态库中提取所需的目标文件,并将它们嵌入到可执行文件中。
  • 动态库:动态库文件是一个共享对象,包含了可以在多个程序中共享的代码。操作系统通过动态链接器(如 Linux 上的 ld.so)负责加载动态库并解析符号。

8. 进阶话题

如何处理库版本

库的版本管理对于动态库尤为重要。常见的方法是使用符号链接或者版本控制机制来管理不同版本的动态库。

库文件的符号表与重定位

库文件中的符号表包含了函数和变量的符号信息。链接器会根据符号表进行符号解析和重定位。

库的跨平台使用

动态库的跨平台使用通常依赖于编译时指定的架构和平台。使用如 autoconfCMake 等工具可以帮助开发者更好地进行跨平台构建。


结论

静态库与动态库在 Linux 系统中的应用各有优势与劣势。静态库适用于需要独立性较强的程序,而动态库则适用于内存共享和版本更新更加灵活的场景。在实际开发中,开发者应根据应用的需求、维护成本和性能要求来选择合适的库类型。

本篇笔记:


感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!!

相关文章:

【Linux探索学习】第二十五弹——动静态库:Linux 中静态库与动态库的详细解析

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在 Linux 系统中&#xff0c;静态库和动态库是开发中常见的两种库文件类型。它们在编译、链接、内存管理以及程序的性能和可维护性方面有着…...

远程和本地文件的互相同步

文章目录 1、rsync实现类似git push pull功能1. 基础概念2. 示例操作3. 定制化和进阶用法4. 定时同步&#xff08;类似自动化&#xff09; 2 命令简化1. 动态传参的脚本2. Shell 函数支持动态路径3. 结合环境变量和参数&#xff08;更简洁&#xff09;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 简介 结巴分词&#xff08;Jieba&#xff09;是一个…...

探索式测试

探索式测试是一种软件测试风格&#xff0c;它强调独立测试人员的个人自由和职责&#xff0c;为了持续优化其工作的价值&#xff0c;将测试学习、测试设计、测试执行和测试结果分析作为相互支持的活动&#xff0c;在整个项目实现过程中并行地执行。 选择合适的探索式测试方法我…...

服务器数据恢复—raid5故障导致上层ORACLE无法启动的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台服务器上的8块硬盘组建了一组raid5磁盘阵列。上层安装windows server操作系统&#xff0c;部署了oracle数据库。 raid5阵列中有2块硬盘的硬盘指示灯显示异常报警。服务器操作系统无法启动&#xff0c;ORACLE数据库也无法启动。 服…...

ISP各模块功能介绍

--------声明&#xff0c;本文为转载整理------- ISP各个模块功能介绍&#xff1a; 各模块前后效果对比&#xff1a; 黑电平补偿&#xff08;BLC&#xff09; 在理想情况下&#xff0c;没有光照射的像素点其响应值应为0。但是&#xff0c;由于杂质、受热等其它原因的影响&…...

Python 数据建模完整流程指南

在数据科学和机器学习中&#xff0c;建模是一个至关重要的过程。通过有效的数据建模&#xff0c;我们能够从原始数据中提取有用的洞察&#xff0c;并为预测或分类任务提供支持。在本篇博客中&#xff0c;我们将通过 Python 展示数据建模的完整流程&#xff0c;包括数据准备、建…...

深入学习RocketMQ

参考&#xff1a;RocketMQ从从入门到精通_rocketmq入门到精通-CSDN博客 1、消息的类型 普通消息 顺序消息 延时消息 批量消息 事务消息 2、在java中使用 2.1、pom.xml中加入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId…...

国产编辑器EverEdit - 扩展脚本:关闭所有未修改文档

1 扩展脚本&#xff1a;关闭所有未修改文档 1.1 应用场景 当用户打开过多文档时&#xff0c;部分文档已经修改&#xff0c;而大部分没有修改&#xff0c;为了减少在众多已打开文档中来回跳转的不便&#xff0c;可以将没有修改的文档全部关闭&#xff0c;但目前提供的快速关闭窗…...

数据结构二叉树-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&#xff08;You Only Look Once&#xff09;和OpenCV实现车道线和车辆检测&#xff0c;目标是创建一个可以检测道路上的车道并识别车辆的系统&#xff0c;并估计它们与摄像头的距离。该项目结合了计算机视觉技术和深度学习物体检测。 1、系统主要功能 车道检测&am…...

代码随想录算法训练营第六十天|KM94.城市间货物运输Ⅰ|KM95.城市间货物运输Ⅱ|KM96.城市间货物运输Ⅲ

94. 城市间货物运输 I 2、Bellman_ford队列优化算法&#xff08;又名SPFA&#xff09; SPFA是对Bellman_ford算法的优化&#xff0c;由于Bellman_ford 算法 每次都是对所有边进行松弛&#xff0c;其实是多做了一些无用功。其实只需要对 上一次松弛的时候更新过的节点作为出发节…...

人工智能学习路线全链路解析

一、基础准备阶段&#xff08;预计 2-3 个月&#xff09; &#xff08;一&#xff09;数学知识巩固与深化 线性代数&#xff08;约 1 个月&#xff09;&#xff1a; 矩阵基础&#xff1a;回顾矩阵的定义、表示方法、矩阵的基本运算&#xff08;加法、减法、乘法&#xff09;&…...

C++语言的学习路线

C语言的学习路线 C是一种强大的高级编程语言&#xff0c;广泛应用于系统软件、游戏开发、嵌入式系统和高性能应用等多个领域。由于其丰富的功能和灵活性&#xff0c;C是一门值得深入学习的语言。本文旨在为初学者制定一条系统的学习路线&#xff0c;帮助他们循序渐进地掌握C语…...

用于与多个数据库聊天的智能 SQL 代理问答和 RAG 系统(3) —— 基于 LangChain 框架的文档检索与问答功能以及RAG Tool的使用

介绍基于 LangChain 框架的文档检索与问答功能&#xff0c;目标是通过查询存储的向量数据库&#xff08;VectorDB&#xff09;&#xff0c;为用户的问题检索相关内容&#xff0c;并生成自然语言的答案。以下是代码逻辑的详细解析&#xff1a; 代码结构与功能 初始化环境与加载…...

20250110doker学习记录

1.本机创建tts环境。用conda. 0.1安装。我都用的默认&#xff0c;你也可以。我安装过一次&#xff0c;如果修复&#xff0c;后面加 -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的编译版本&#xff1a;原理和概念 理解 C标准 和 C编译版本 的关系是学习 C 的一个重要部分。这两者虽然看似相关&#xff0c;但实际上分别涉及了不同的概念和技术。下面将通过层次清晰的解释&#xff0c;帮助新手理解这两个概念的差异、特点及其相互关系。 一、C标…...

python学习笔记—17—数据容器之字符串

1. 字符串 (1) 字符串能通过下标索引来获取其中的元素 (2) 旧字符串无法修改特定下标的元素 (3) index——查找字符串中任意元素在整个字符串中的起始位置(单个字符或字符串都可以) tmp_str "supercarrydoinb" tmp_position1 tmp_str.index("s") tmp_p…...

UE5 使用内置组件进行网格切割

UE引擎非常强大&#xff0c;直接内置了网格切割功能并封装为蓝图节点&#xff0c;这项功能在UE4中就存在&#xff0c;并且无需使用Chaos等模块。那么就来学习下如何使用内置组件实现网格切割。 1.配置测试用StaticMesh 对于被切割的模型&#xff0c;需要配置一些参数。以UE5…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...