【Linux】—— 详解动态库和静态库

前言:

  • 本期我将要给大家讲解的是有关 动态库和静态库 的相关知识!!!

目录

序言

见一见库

为什么要有库 

(一)动态库(.so)

1.基本概念

2.命名规则

3.制作动态库 

(二)静态库(.a)

1.基本概念

2.命名规则

3.制作静态库 

(三)什么叫 fPIC

(四)对比静态库和动态库

总结


序言

见一见库

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)动态库(.so、.dll)

  • 所谓静态、动态是指链接。简单回顾一下将一个程序编译成可执行程序的步骤:

在正式的讲解动态库和静态库之前,我们先带带大家认识我们平时写 C/C++代码时用到的库

  •  " ls /usr/lib64/libc* ” 这个命令用于列出匹配模式 "libc*" 的文件或目录

  •  其次,我们也可以去查看平时我们经常用到的:

【解释说明】

  1. 系统已经预装了C/C++的头文件和库文件,头文件提供方法说明,库提供方法的实现,头和库是有对应关系的,是要组合到一起使用的;
  2. 头文件是在预处理阶段装入的,链接本质其实就是链接库!!!


为什么要有库 

其实这一点大家都能理解(造轮子和用轮子的问题):

  1. 库是一组预先编写好的代码、程序或函数的集合,用于解决特定类型问题或提供特定功能;
  2. 这些代码通常被封装成模块,以便在开发软件时能够重用、共享和简化代码。

在我们学习阶段大家可以更多的尝试去造轮子,熟悉其中的一些思想及其方法等,等到大家上班的就是 “用轮子” 的较多了。


(一)动态库.so

1.基本概念

  • 动态库是一种在运行时加载和链接的库文件;
  • 与静态库相比,动态库在程序执行之前不会被完全链接到可执行文件中,而是在运行时被动态地加载到内存并链接。

2.命名规则

在命名动态库时,通常会遵循一定的命名规则以确保一致性和可读性。以下是一些常见的动态库命名规则:

  1. 前缀:动态库名称通常以lib开头作为前缀,表示这是一个库文件。

  2. 中间部分:中间部分通常是描述库的名称或功能的字母数字组合。可以根据库的用途或模块来命名,以便更好地理解其功能。建议使用小写字母和下划线进行命名,以增加可读性。

  3. 扩展名:动态库的扩展名取决于操作系统和平台。在Linux上,通常是.so(共享对象);在Windows上,通常是.dll(动态链库);在Mac上,通常是.dylib(动态库)。

💨 综合起来,一个典型的动态库命名可能如下所示: 


3.制作动态库 

在Linux系统上创建动态库(也称为共享库或.so文件)涉及编写、编译和链接一组源代码文件,以生成可在多个应用程序之间共享的动态链接库。

以下是创建Linux动态库的一般步骤:

1️⃣编译源代码

使用编译器将源代码编译成位置无关的目标文件,通常使用.o文件扩展名。为了生成动态库,需要使用 -fPIC 选项(位置无关代码)来确保目标文件可以在内存中加载并重定位。

  • 例如,在Linux系统上,可以使用gcc编译器编译一个源文件并生成位置无关的目标文件: 


2️⃣创建动态库

使用共享库工具(gcc也可以用于此)将目标文件链接到一个共享库文件中。通常,Linux动态库的命名约定是以.so结尾,并且通常有版本号。

  • 以下是创建动态库的示例,命名为 libmymath.so


3️⃣运行代码:

我这里是把文件打包拷贝到 【otherPerson】目录下执行:

💨 紧接着执行:gcc -o mytest main.c (发现报错了!!)

 【解释说明】

  • 因为在当前路径下头文件并没有找到,因为并没有进行安装

💨 接下来,再次执行:gcc -o mytest main.c -I include (发现还是报错了!!)

【解释说明】

  • 因为在当前路径下库并没有找到

💨 接下来,再次执行:gcc -o mytest main.c -I include -L lib(发现还是报错了!!)

💨 接下来,再次执行:gcc -o mytest main.c -I include -L lib -lmymath(发现还是报错了!!)

这次,我们发现程序正常运行成功了。紧接着,我们执行相应的文件:

 【解释说明】

  • 此时,有的小伙伴可能就比较疑惑:“我不是已经告诉了系统,我的库在哪里并且告诉叫什么了吗?为什么还是找不到呢?”
  • 其实,gcc时只是告诉了编译器,而没有真正的告诉操作系统!运行的时候因为我的 .so 并不是在默认的路径下,所以os 依旧找不到!!


⭐️ 如何让系统能够找到动态库:

  • 1、通过环境变量(临时方案)

环境变量中确实没有我们当前的路径,因此第一种解决方法就是把我们当前的路径加入到系统的环境变量中。具体如下:

但是,这个方法是临时性的,当我们重新打开去运行时就失效了:


  • 2、指定路径下建立软链接(永久版本)


  • 3、配置文件方案

在配置之前,需要先把上述使用软链接创建的删除掉:

💨如果安装在其他目录,需要将其添加到/etc/ld.so.conf.d/文件中,步骤如下:

1.前期准备

2.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

 3.运行ldconfig ,该命令会重建/etc/ld.so.conf.d/文件


(二)静态库.a

1.基本概念

  1. 静态库是一种在编译时链接到可执行程序的库文件形式;
  2. 它是由一组预编译的目标文件(Object File)组成,其中包含了函数、变量和其他可重用的代码和数据。

💨 需要注意一点:库云服务器默认没有静态!!!


2.命名规则

在 Linux 上,静态库的命名规则通常是:

lib<library_name>.a

其中:

  • lib 是固定的前缀,表示这是一个库文件。
  • library_name 表示该库的名称或功能,建议使用小写字母和下划线进行命名,以增加可读性。
  • .a 是静态库的扩展名,表示这是一个归档文件 (archive file)。静态库通常以 .a 作为扩展名。

💨 综合起来,一个典型的动态库命名可能如下所示: 


3.制作静态库 

创建静态库涉及编写、编译和打包一组代码文件,以便它们可以在其他程序中静态链接和重用。

以下是创建静态库的一般步骤:

  • 1、编写使用创建的静态库的测试代码:
/myadd.h/#ifndef __ADD_H__#define __ADD_H__ int add(int a, int b); #endif // __ADD_H__/myadd.c/#include "myadd.h"int add(int a, int b){return a + b;}/mysub.h/#ifndef __SUB_H__#define __SUB_H__ int mysub(int a, int b); #endif // __SUB_H__/mysub.c/#include "mysub.h"int sub(int a, int b){return a - b;}///main.c#include <stdio.h>#include "myadd.h"#include "mysub.h"int main(){int a = 10;int b = 3;printf("add(10, 3)=%d\n", a, b, add(a, b));printf("add(10, 3)=%d\n", a, b, sub(a, b));return 0;}
  • 2、使用编译器将源代码编译成目标文件(通常是中间代码文件),编译时,使用适当的编译选项以确保生成的目标文件是可链接的(注意带参数-c,否则直接编译为可执行文件

  • 3、然后,通过ar工具将目标文件打包成.a静态库文件

【注意】 

  •  大一点的项目会编写makefile文件(CMake等等工程管理工具)来生成静态库,输入多个命令太麻烦了

  • 4、Linux下使用静态库,只需要在编译的时候,指定静态库的搜索路径(-L选项)、指定静态库名(不需要lib前缀和.a后缀,-l选项)

【注意】

  •  -L:表示要连接的库所在目录
  •  -l:指定链接时需要的动态库,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a或.so来确定库的名称。

【小结】

  1. 创建静态库涉及编写、编译、打包目标文件,然后将静态库链接到其他程序中;
  2. 这种方法适用于小型项目,或者当需要确保可执行文件与特定版本的库一起分发时;
  3. 但需要注意的是,静态库会增加可执行文件的大小,并且不支持动态更新。如果需要更大的灵活性和共享性,可以考虑使用动态库。 

(三)什么叫 fPIC

fPIC 是 GCC编译器的一个选项,用于生成位置无关代码(Position Independent Code,PIC)。位置无关代码是一种可以在内存中加载并且不受加载地址限制的代码,因此适合用于创建共享库(动态链接库,也称为.so文件)以及在多个进程之间共享的代码。 

  • 我们以下图进行分析: 

【解释说明】

  1. 当一个库真正的映射到地址空间的时候,它的起始地址才能真正的被确定下来!而它的库在形成的时候并不是使用的绝对地址,而是使用的相对于起始地址的偏移量;
  2. 有了上述这样的方法,使得动态库在进程的地址空间中能够随便的进行加载,而与我们加载到地址空间的什么位置毫无关系。因为OS是知道起始地址的,因此在我们链接时只需把对应的偏移量加载进来,OS根据起始地址 + 偏移量的操作即可完成相应的地址映射;
  3. 上述这样的库就称为动态库,这种库中的地址就称为 fPIC。

(四)对比静态库和动态库

动态库和静态库是两种不同的库文件类型,它们在编程和软件开发中有着重要的区别。以下是它们之间的主要区别:

  1. 加载时机:

    • 静态库:在编译时将库的代码和数据链接到可执行文件中,形成一个单独的可执行文件。这意味着库的代码在程序运行之前已经完全被包含在可执行文件中。
    • 动态库:库的代码和数据在程序运行时才被加载到内存中。可执行文件包含了对库的引用,但实际的库代码在程序启动时或首次使用时才会被加载。
  2. 文件大小:

    • 静态库:由于库的代码被完全复制到每个可执行文件中,因此可执行文件通常比较大。
    • 动态库:多个可执行文件可以共享相同的库,因此动态库可以减小可执行文件的大小。
  3. 内存占用:

    • 静态库:每个运行的程序实例都包含库的一个拷贝,因此可能会占用更多的内存。
    • 动态库:多个程序实例可以共享同一个库的实例,节省内存。
  4. 可扩展性:

    • 静态库:每次引入新的库版本都需要重新编译和链接,不够灵活。
    • 动态库:可以在不修改可执行文件的情况下,替换或升级库的版本,提供更好的可扩展性。
  5. 加载速度:

    • 静态库:由于库的代码已经包含在可执行文件中,因此加载速度较快。
    • 动态库:需要在运行时加载,可能会略微减慢程序启动速度。

总结

以上便是本文关于动静态的全部内容了。接下来,简单的回顾总结一下!!

  1. 动态库和静态库各自有其优势和劣势,具体选择取决于项目的需求和设计考虑;
  2. 通常,动态库在节省内存、库的更新和维护方面更有优势,而静态库在加载速度和跨平台兼容性方面更有优势

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习笔记】CF1817F Entangled Substrings(基本子串结构)

前置知识&#xff1a;基本子串结构&#xff0c;SAM的结构和应用 学长博客 字符串理论比较抽象&#xff0c;建议直观的去理解它 子串 t t t的扩展串定义为 ext(t) : t ′ \text{ext(t)}:t ext(t):t′&#xff0c;满足 t t t是 t ′ t t′的子串&#xff0c;且 occ(t) occ(t…

2023年十大开源项目:革新技术创新

来源整理 : 小托 | 开源社翻译组PM 翻译 : 张锋 | 开源社翻译 Open-source projects have revolutionized the world of software development by fostering innovation, collaboration, and community-driven contributions. These projects are often the backbone of countl…

PHP8的继承和多态-PHP8知识详解

我们在前面的时候讲过《面向对象编程的特点》时&#xff0c;面向对象编程具有3大特点&#xff1a;封装性、继承性和多态性。 继承和多态的根本作用就是完成代码的重用。下面就来讲解php8的继承和多态。 1继承 子类可以继承父类的所有成员变量和成员方法&#xff0c;包括构造方…

玄子Share 设计模式 GOF 全23种 + 七大设计原则

玄子Share 设计模式 GOF 全23种 七大设计原则 前言&#xff1a; 此文主要内容为 面向对象七大设计原则&#xff08;OOD Principle&#xff09;GOF&#xff08;Gang Of Four&#xff09;23种设计模式拓展的两个设计模式 简单工厂模式&#xff08;Simple Factory Pattern&#x…

Fake Maxpooling 二维滑动窗口

先对每一行求一遍滑动窗口&#xff0c;列数变为(列数-k1) 再对每一列求一遍滑动窗口&#xff0c;行数变为(行数-k1) 剩下的就是每一个窗口里的最大值啦 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing nam…

【强化学习】基础概念

1. Agent (智能体) 智能体是进行决策和学习的实体&#xff0c;它能感知环境的状态&#xff0c;并基于策略采取动作以影响环境。智能体的目标是通过与环境的交互获得最大化的累积奖励。 2. Environment (环境) 环境是智能体所处的外部系统&#xff0c;它与智能体交互。环境的…

【算法】莫队

这篇博客起源于本人把一道 p o w ( 2 , n ) pow(2,n) pow(2,n) 的问题考虑成求组合数前缀和的问题qwq&#xff0c;于是接触到了这个新算法来总结一下 参考自这篇文章&#xff0c;写得太好了 首先是一道模板题 题目意思是&#xff0c;给出一个数组a&#xff0c;再给出多个区…

无人直播间

失败&#xff01;&#xff01; 采用 ffmpeg 技术进行推流 推流代码&#xff1a; 【需要将rtmp替换为你的推流地址】 ffmpeg -re -stream_loop -1 -i "rain.mp4" -c copy -f flv ""推流地址获取 以哔哩哔哩为例 点击下方链接 开播设置 - 个人中心 - …

【MATLAB源码-第39期】基于m序列/gold序列的直接扩频通信仿真,编码方式采用卷积码,调制方式采用BPSK。

1、算法描述 直接序列扩频通信系统的仿真一般包括以下几个主要步骤&#xff1a;信号产生、扩频、卷积编码、BPSK调制、信道传输、BPSK解调、卷积码译码和解扩。 信号产生&#xff1a; 首先&#xff0c;产生一个二进制数据序列作为待发送的信息位。 扩频&#xff1a; 采用m序列…

如何开始着手一篇Meta分析 | Meta分析的流程及方法

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

十五、异常(3)

本章概要 捕获所有异常 多重捕获栈轨迹重新抛出异常精准的重新抛出异常异常链 捕获所有异常 可以只写一个异常处理程序来捕获所有类型的异常。通过捕获异常类型的基类 Exception&#xff0c;就可以做到这一点&#xff08;事实上还有其他的基类&#xff0c;但 Exception 是所…

鸿鹄工程项目管理系统 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离构建工程项目管理系统

项目背景 一、随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;公司对内部工程管理的提升提出了更高的要求。 二、企业通过数字化转型&#xff0c;不仅有利于优化业务流程、提升经营管理…

HTML——列表,表格,表单内容的讲解

文章目录 一、列表1.1无序&#xff08;unorder&#xff09;列表1.2 有序&#xff08;order&#xff09;列表1.3 定义列表 二、表格**2.1 基本的表格标签2.2 演示 三、表单3.1 form元素3.2 input元素3.2.1 单选按钮 3.3 selcet元素 基础部分点击&#xff1a; web基础 一、列表 …

【JavaEE】CAS(Compare And Swap)操作

文章目录 什么是 CASCAS 的应用如何使用 CAS 操作实现自旋锁CAS 的 ABA 问题CAS 相关面试题 什么是 CAS CAS&#xff08;Compare and Swap&#xff09;是一种原子操作&#xff0c;用于在无锁情况下保证数据一致性的问题。它包含三个操作数——内存位置、预期原值及更新值。在执…

轻量自高斯注意力(LSGA)机制

light&#xff08;轻量&#xff09;Self-Gaussian-Attention vision transformer&#xff08;高斯自注意力视觉transformer&#xff09; for hyperspectral image classification&#xff08;高光谱图像分类&#xff09; 论文&#xff1a;Light Self-Gaussian-Attention Vision…

完整指南:如何使用 Node.js 复制文件

文件拷贝指的是将一个文件的数据复制到另一个文件中&#xff0c;使目标文件与源文件内容一致。Node.js 提供了文件系统模块 fs&#xff0c;通过该模块可以访问文件系统&#xff0c;实现文件操作&#xff0c;包括拷贝文件。 Node.js 中文件拷贝方法 在 Node.js 中&#xff0c;有…

基于微信小程序的宠物寄养平台小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

预编译(1)

目录 预定义符号&#xff1a; 使用&#xff1a; 结果&#xff1a; 预编译前后对比&#xff1a; #define定义常量&#xff1a; 基本语法&#xff1a; 举例1&#xff1a; 结果&#xff1a; 预编译前后对比&#xff1a; 举例2&#xff1a; 预编译前后对比&#xff1a; 注…

ELK介绍

一、前言 前面的章节我们介绍通过ES Client将数据同步到ElasticSearch中&#xff0c;但是像日志这种数据没有必要自己写代码同步到ES那样会折腾死&#xff0c;直接采用ELK方案就好&#xff0c;ELK是Elasticsearch、Logstash、Kibana三款开源软件的缩写&#xff0c;ELK主要用于…

P2PNet-Soy原理梳理

前文总结了P2PNet源码以及P2PNet-Soy源码实现方法&#xff0c;相关链接如下&#xff1a; 人群计数P2PNet论文&#xff1a;[2107.12746] Rethinking Counting and Localization in Crowds:A Purely Point-Based Framework (arxiv.org) p2p人群计数源码&#xff1a;GitHub - Te…