Linux_动、静态库

news2024/7/4 23:30:51

目录

一、静态库

1、静态库的概念 

2、制作静态库的指令

3、制作静态库

4、链接静态库

二、动态库 

1、动态库的概念

2、制作动态库的指令 

3、制作动态库 

4、链接动态库

5、动态库的加载 

三、静态库与动态库的区别

结语


前言:

        在Linux下大部分程序进行编译时,都会接触静态库或动态库,因此动静态库在Linux下是个很重要的概念,他们都是文件,其中静态库后缀是.a,动态库后缀是.so。动静态库里保存的是函数的具体方法,他们的不同点在于链接阶段时,静态库会把方法直接拷贝到程序中,而动态库会把方法加载到内存中,并且在可执行程序中记录了动态库在内存的地址,以便在运行时能够让可执行程序从内存中定位具体方法。

一、静态库

1、静态库的概念 

         静态库是由.o文件打包而来的,因此库里面保存的是二进制,程序链接静态库时,会将静态库里的方法拷贝至可执行程序,所以使用静态库会导致可执行程序变大,则会占用内存和磁盘的空间,但是该可执行程序运行时不再需要链接外部的库,程序的独立性较强。

2、制作静态库的指令

        静态库的命名方式必须以lib为前缀,以.a为后缀,使用指令生成静态库:

ar -rc libxxx.a xxx.o
//将xxx.o文件打包成静态库

         这里.o文件可以是多个,即可以将多个.o文件打包成静态库,由于静态库存放的是函数方法,所以要先有一个.c源文件存放函数实现,以及有一个.h文件存放函数声明,代码如下:

//math.h
#pragma once
#include<stdio.h>

int Add1(int x,int y);


//math.c
#include"math.h"

int Add1(int x,int y)
{
    return x+y;
}

        并且在主函数中调用函数add:

//test.c
#include"math.h"

int main()
{
    int sum = Add1(5,3);
    printf("sum=%d\n",sum);
    return 0;
}

        先测试以上代码是否正确:

        从结果看以上代码的逻辑没问题。

3、制作静态库

        写一个makefile,便于完成静态库的制作,makefile的具体工作:生成math.c的.o文件,然后打包.o文件生成静态库文件,并且创建一个目录,将.h和.a文件打包到该目录下,这样直接将整个目录给到外部使用,.h文件主要是让用户知道该静态库有哪些方法可以被调用,类似说明书的作用。

        makefile代码如下:

libmath.a:math.o
	ar -rc $@ $^

math.o:math.c
	gcc -c $^ -o $@

.PHONY:clean
clean:
	rm -f *.o *.a

.PHONY:mk
mk:
	mkdir -p lib_math/include
	mkdir -p lib_math/libmath
	cp *.a lib_math/libmath
	cp *.h lib_math/include

        测试结果如下:

4、链接静态库

二、动态库 

        正常编译一个程序时,用的指令是gcc xxx.c -o a.out,该指令默认让编译器和链接器到指定的路径下去寻找.so(动态库)文件,给指令加上-static后就去指定的路径下寻找.a(静态库)文件,共同点是寻找的路径是被设置好的(寻找#include的头文件也是如此,系统默认到指定路径下找头文件),很明显上面自己制作的静态库是在我们自己创建的目录下,所以需要对默认指令进行路径指定化,并且寻找头文件math.h也需要指定路径,操作如下:

gcc test.c -I ./lib_math/include -L ./lib_math/libmath -lmath

        测试结果:

        这里要注意两个细节:

1、-L的时候要精确到.a文件,-I的时候不需要精确到具体的.h文件是因为代码中已经用include包了那个.h文件。

2、链接.a文件的时候用-l并且后面紧跟库的名称,并且该库的名称要去掉前缀和后缀,即只留下和#include<>尖括号中一样的名称。

        运行a.out:

        发现运行结果正确,并且细心观察此时a.out文件内容较大,是因为静态库在程序链接时会将对应方法拷贝到程序中形成最终的可执行程序。

1、动态库的概念

         动态库也是由.o文件打包而来的,生成.o文件后对.o文件进行加工得到动态库,跟静态库不同的是,他的文件后缀是.so,并且动态库类似可执行程序(静态库是一个文件),因为他需要被加载到内存中以便让多个进程共用其方法,所以他不必拷贝到程序中节省了内存和磁盘的空间。

2、制作动态库的指令 

         首先使用gcc编译指令形成.o文件,只不过该指令中需要加上选项-fPIC,指令如下:

gcc -fPIC -c xxx.c
//执行该指令得到一个xxx.o文件
//fPIC:产生位置无关码,即偏移量
//因为动态库加载到内存中是不固定地址的,
//所以需要根据偏移量找到在进程地址空间中加载的动态库的方法位置,即动态库的起始地址+偏移量。

         接着对生成的.o文件进行打包即可生成动态库,和制作静态库不一样,制作动态库的指令也是gcc,只不过需要加上-shared选项,并且对动态库的命名方式需加前缀lib和后缀.so

gcc -shared -o libxxx.so xxx.o
//执行该指令得到一个xxx.so的动态库

3、制作动态库 

         1、沿用上文的头文件、源文件,首先用math.c生成动态库所需的.o文件:

        2、打包.o文件形成动态库:

         3、和上述静态库一样的逻辑,将.h文件和.so文件放到一个目录下:

4、链接动态库

         因为编译的指令始终是gcc,所以链接动态库的指令和链接静态库是一样的,又因为是链接我们自己制作的库,所以需要用-I和-L来指定路径,并且连接指定库时要去掉前缀lib和后缀.so,链接指令如下:

gcc test.c -I ./lib_math/include -L ./lib_math/libmath -lmath

        测试结果:


         从结果看果然生成了a.out,这一切看起来都很顺序,然后运行a.out后发现: 

        报错的原因是找不到动态库,虽然在gcc指令中指定了库的路径,但是这只是让编译器在编译的时候可以找到库,然而动态库本身需要被加载到内存中,所以动态库也需要让加载器知道动态库的路径,而加载器默认会去/lib64这个目录下查找,所以我们需要通过某种方式让我们的的动态库出现在这个目录下

        用软链接的方式: 

        发现结果是可行的,因此得出一个结论:连接动态库还需要将库文件安装到系统下,并且动态链接后形成的可执行程序确实比静态链接形成的可执行程序要小,原因就是程序中用到的动态库方法被加载到内存中的共享区供所有进程使用,并没有直接拷贝到程序中。 

5、动态库的加载 

        从上文可以知道,动态库会被加载到内存中,可执行程序会保存动态库在内存中的地址,以便在程序运行时能够根据该地址找到具体的方法,动态库只会被加载一份至物理内存中,只不过多个进程的共享区会指向同一个物理内存,这样一来就无需加载相同的库文件至内存中。动态库和内存以及进程的关系示意图如下:

三、静态库与动态库的区别

1、静态库在链接时会把调用方法拷贝到程序中,从而形成最终的可执行程序。动态库不会直接拷贝,而是在程序运行时加载到内存中,让程序动态调用。

2、静态库导致可执行程序变大。而动态库不会让可执行程序变大。

3、制作静态库的指令是ar -ra。制作动态库的指令是gcc -shared -o,并且需用-fPIC形成.o文件。

4、使用静态库时无需将静态库放到系统路径下。使用动态库时需要将动态库放到系统路径下。

5、静态库独立性强,依赖性低。动态库独立性低,依赖性强。

结语

         以上就是关于Linux的动静态库讲解,只要我们的程序用到了第三方库那么就离不开动静态库,因此大部分的程序都要和动静态库打上交道,动静态库最核心的点在于静态库会加载到程序中,而动态库会加载到内存中,通过这两点再向外拓展。

        最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!  

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

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

相关文章

颍川韩氏,来自战国七雄韩国的豪族

颍川是战国七雄韩国故土&#xff0c;韩国被秦国灭国后&#xff0c;王公贵族们除了坚决反秦的被杀了外&#xff0c;大部分都留存了下来。这些人在楚、汉反秦战争中&#xff0c;成为反秦统一战线的重要力量&#xff0c;其中两人先后被封为重新恢复的韩国的国王。 一个是横阳君韩…

240630_昇思学习打卡-Day12-Transformer中的Multiple-Head Attention

240630_昇思学习打卡-Day12-Transformer中的Multiple-Head Attention 以下为观看大佬课程及查阅资料总结所得&#xff0c;附大佬视频链接&#xff1a;Transformer中Self-Attention以及Multi-Head Attention详解_哔哩哔哩_bilibili&#xff0c;强烈建议先去看大佬视频&#xff…

【Linux】IO多路复用——select,poll,epoll的概念和使用,三种模型的特点和优缺点,epoll的工作模式

文章目录 Linux多路复用1. select1.1 select的概念1.2 select的函数使用1.3 select的优缺点 2. poll2.1 poll的概念2.2 poll的函数使用2.3 poll的优缺点 3. epoll3.1 epoll的概念3.2 epoll的函数使用3.3 epoll的优点3.4 epoll工作模式 Linux多路复用 IO多路复用是一种操作系统的…

人工智能导论速成笔记

文章目录 前言考试题型第一章、人工智能导引 (10分 )课后习题第二章、Python基础 (10分 )*文件读写NumPy的使用Python绘图基础第三章、机器学习初步(15分 )逻辑回归分类(Logistic Regression)*,3.5线性回归预测(Linear Regression)*,3.6 、3.7、 3.8聚类 3.9第四章、自然语言…

郑州高校大学智能制造实验室数字孪生可视化系统平台建设项目验收

随着制造业的转型升级&#xff0c;智能化、信息化已成为制造业发展的必然趋势。数字孪生技术作为智能制造领域的关键技术之一&#xff0c;它通过构建与实体系统相对应的虚拟模型&#xff0c;实现对实体系统的实时监测、预测和优化&#xff0c;为制造业的智能化、信息化提供了强…

叶老师的新水杯c++

题目描述 最近叶老师换了个带吸管的水杯。 贝贝发现当叶老师使用带吸管的水杯时&#xff0c;每天会喝 x 毫升的水。而使用不带吸管的水杯时&#xff0c;每天会喝 y 毫升的水。 请问在 n 天的时间内&#xff0c;叶老师喝水量的上限与下限相差多少&#xff1f; 输入 第一行为…

Advanced RAG 09:『提示词压缩』技术综述

编者按&#xff1a; 如何最大限度地发挥 LLMs 的强大能力&#xff0c;同时还能控制其推理成本&#xff1f;这是当前业界研究的一个热点课题。 针对这一问题&#xff0c;本期精心选取了一篇关于"提示词压缩"(Prompt Compression)技术的综述文章。正如作者所说&#xf…

VMware17.0 安装过程

VMware17.0 VMware 17.0 是一款功能强大的虚拟机软件&#xff0c;用于在计算机上创建和管理虚拟机。它能够同时运行多个操作系统&#xff0c;如 Windows、Linux 等&#xff0c;并且在这些虚拟机之间提供无缝的切换和共享功能。 VMware 17.0 支持最新的硬件和操作系统&#xf…

区间动态规划——最长回文子串(C++)

难得心静。 ——2024年6月30日 什么是区间动态规划&#xff1f; 区间动态规划通常以连续区间的求解作为子问题&#xff0c;例如区间 [i, j] 上的最优解用dp[i][j]表示。先在小区间上进行动态规划得到子问题的最优解&#xff0c;再利用小区间的最优解合并产生大区间的最优解。 …

ComfyUI高清放大的四种方式(工作流附件在最后)

方式一&#xff1a;Latent放大工作流 1.工作流截图 方式二&#xff1a;ESRGAN&#xff08;传统模型&#xff09;放大工作流 方式三&#xff1a;算法放大&#xff08;后期处理&#xff09;工作流 方式四&#xff1a;Ultimate SD Upscale工作流 这个方式的优势是对于显存底的用…

WP黑格导航主题BlackCandy

BlackCandy-V2.0全新升级&#xff01;首推专题区(推荐分类)更多自定义颜色&#xff01;选择自己喜欢的色系&#xff0c;焕然一新的UI设计&#xff0c;更加扁平和现代化&#xff01; WP黑格导航主题BlackCandy

代码随想录第37天|动态规划

01背包理论基础 参考 01背包: 每个物品只有一个, 只要选或不选两个选项 暴力解法: 回溯法枚举 dp[i][j]: i 表示 0 ~ i 的物品, j 表示容量, 数值表示当前的最大价值递推公式: max(dp[i-1][j], dp[i-1][j-weight[i]] value[i])初始化: j 0 时, 无法放任何有价值的物品, d…

目标检测常用涨点方法:注意力机制小结(空间注意力、通道注意力、CBAM等)

1.通道注意力 通道注意力&#xff08;Channel Attention&#xff09;是在通道维度上对输入数据进行学习&#xff0c;再对不同的通道分配相应的权重表示重要性&#xff0c;从而达到“分配注意力”的效果。SENet&#xff08;Squeeze and Excitation networks) 是一个典型的使用通…

MySQL高级-事务-并发事务演示及隔离级别

文章目录 0、四种隔离级别1、创建表 account2、修改当前会话隔离级别为 read uncommitted2.1、会出现脏读 3、修改当前会话隔离级别为 read committed3.1、可以解决脏读3.2、会出现不可重复读 4、修改当前会话隔离级别为 repeatable read&#xff08;默认&#xff09;4.1、解决…

C++(Python)肥皂泡沫普拉托边界膜曲面模型算法

&#x1f3af;要点 &#x1f3af;肥皂泡二维流体模拟 | &#x1f3af;泡沫普拉托边界膜曲面模型算法演化厚度变化 | &#x1f3af;螺旋曲面三周期最小结构生成 &#x1f4dc;皂膜用例&#xff1a;Python计算物理粒子及拉格朗日和哈密顿动力学 | Python和MATLAB粘性力接触力动…

ELK企业级实战

一、Elstic stack在企业的常⻅架构 https://www.bilibili.com/video/BV1x94y1674x/?buvidXY705117E90F73A790429C9CFBD5F70F22168&vd_source939ea718db29535a3847d861e5fe37ef ELK 解决取得问题 痛点1: ⽣产出现故障后&#xff0c;运维需要不停的查看各种不同的⽇志进⾏…

10款好用不火的PC软件,真的超好用!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/市场上有很多软件&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;它们的作用非常强大&#xff0c;简洁…

骁龙相机拍照流程分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 1.deliverInputEvent 拍照点击事件处理 2.submitRequestList Camera 提交拍照请求 3.createCaptureRequest 拍照请求帧数 骁龙相机通过binder 数据传输…

小程序打包

一、manifest.json文件添加小程序id 二、接口校验&#xff0c;后端接口添加正式上线&#xff0c;有域名的地址 然后到微信公众平台-开发管理-服务器域名处配置request合法域名&#xff0c;在 此处能够看到后端的baseUrl 三、项目部署 四、发版 在小程序编辑器里 此处可以在…

微服务之服务保护策略【持续更新】

文章目录 线程隔离一、滑动窗口算法二、漏桶算法三、令牌桶算法 面试题1、Sentinel 限流和Gateway限流的区别 线程隔离 两种实现方式 线程池隔离&#xff08;Hystix隔离&#xff09;&#xff0c;每个被隔离的业务都要创建一个独立的线程池&#xff0c;线程过多会带来额外的CPU…