【Linux系统编程】静态库和共享库

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:Linux系统编程
📣专栏定位:整理一下 C++ 相关的知识点,供大家学习参考~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
🎏唠叨唠叨:在这个专栏里我会整理一些琐碎的 C++ 知识点,方便大家作为字典查询~

静态库和共享库

1. 区别

静态库

静态库在文件中静态展开,所以有多少文件就展开多少次,非常吃内存,100M 展开 100 次,就是 1G ,但是这样的好处就是静态加载的速度快。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WY8zT0Yg-1679977310186)(Linux系统编程.assets/image-20220828214312904.png)]

动态库

使用动态库会将动态库加载到内存,10 个文件也只需要加载一次,然后这些文件用到库的时候临时去加载,速度慢一些,但是很省内存。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tbk18a5d-1679977310188)(Linux系统编程.assets/image-20220828214452492.png)]

优缺点

动态库和静态库各有优劣,根据实际情况合理选用即可。

  • 静态库:对空间要求较低,而时间要求较高的核心程序中。
  • 动态库:对时间要求较低,对空间要求较高。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZejWYSl-1679977310191)(Linux系统编程.assets/image-20220906142434581.png)]

2. 静态库制作

Linuxlibxxx.a

  • lib :前缀(固定)
  • xxx :库的名字,自己起
  • .a :后缀(固定)

Windowslibxxx.lib

静态库生成指令

ar rcs libmylib.a file1.o
  • r - 将文件插入备存文件中
  • c - 建立备存文件
  • s - 索引

生成步骤

第一步: 写好源代码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iCQgWXo7-1679977310192)(Linux系统编程.assets/image-20220828215250237.png)]

第二步: 编译源代码生成 .o 文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HkpzsRqk-1679977310198)(Linux系统编程.assets/image-20220828215350493.png)]

第三步: 制作静态库。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ddciDntN-1679977310209)(Linux系统编程.assets/image-20220828215447563.png)]

第四步: 编译静态库到可执行文件中。

gcc test.c lib库名.a -o a.out

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CwchdyWe-1679977310212)(Linux系统编程.assets/image-20220828220226568.png)]

编译时出现了函数未定义的警告,可以忽略,让系统生成默认的定义。

下图可以发现 test.c 只占用了 209 大小,而 test 却占用了 16752 ,说明静态库是直接编译到文件中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LIhUojAS-1679977310216)(Linux系统编程.assets/image-20220828220531226.png)]

上面出现的警告,可以用编译器隐式声明来解决。编译器只能隐式声明返回值为 int 的函数形式:

int add(int, int)

如果函数不是返回的 int ,则隐式声明失效,所以会警告。

那我们只用在 test.c 中加入函数声明即可:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wU94RvU9-1679977310218)(Linux系统编程.assets/image-20220828221654295.png)]

这时候再编译就不会警告了:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FPUBYSQ2-1679977310219)(Linux系统编程.assets/image-20220828221717703.png)]

但是这样子做需要库的使用者知道库里的函数,然后再一个一个加到代码里,不是很科学,我们可以用下面这种方法来加载静态库。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-huAlQ1Py-1679977310223)(Linux系统编程.assets/image-20220828222251544.png)]

右边的 define 为头文件守卫,防止在代码中多次 include 同一个头文件,多次展开静态库,带来的额外开销。

然后我们同样进行编译,发现也不会报错,但是这样子写更好一些。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2chDyEDB-1679977310224)(Linux系统编程.assets/image-20220828222504612.png)]

当然,我们可以将静态库和头文件分别放至其他目录下,然后再模拟一遍。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aPjoqBHe-1679977310226)(Linux系统编程.assets/image-20220828224844129.png)]

然后运行结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EbS6F6eW-1679977310228)(Linux系统编程.assets/image-20220828224939700.png)]

3. 动态库制作

Linuxlibxxx.so

  • lib :前缀(固定)

  • xxx :库的名字,自己起

  • .so :后缀(固定)

  • Linux 下是一个可执行文件

Windowslibxxx.dll

制作步骤

  1. .c 生成 .o 文件(生成与位置无关的代码 -fPIC
gcc -c add.c -o add.o -fPIC

使用这个参数过后,生成的函数就和位置无关,挂上 @plt 标识,等待动态绑定。

  1. 使用 gcc -shared 制作动态库
gcc -shared -o lib库名.so add.o sub.o div.o
  1. 编译可执行程序时指定所使用的动态库

-l :指定库名;-L :指定库路径

gcc test.c -o a.out -l mymath -L ./lib
  1. 运行可执行程序 ./a.out

过程演示

步骤一:生成位置无关的 .o 文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-weLgB4zZ-1679977310229)(Linux系统编程.assets/image-20220830213028856.png)]

步骤二:制作动态库 gcc -shared -o lib 库名 .so add.o

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FvFofyS6-1679977310231)(Linux系统编程.assets/image-20220830213130736.png)]

步骤三:编译程序

文件分布如下:动态库在 lib 目录下,头文件在 inc 目录下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rbmwUAiz-1679977310232)(Linux系统编程.assets/image-20220830213817870.png)]

下面编译文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vmts60kk-1679977310233)(Linux系统编程.assets/image-20220830213916958.png)]

步骤四:执行文件,出错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3UcVnTxH-1679977310234)(Linux系统编程.assets/image-20220830213945964.png)]

出错原因分析:

  • 连接器:工作于链接阶段,工作时需要 -l-L
  • 动态链接器:工作于程序运行阶段,工作时需要提供动态库所在目录位置。

解决方法

(1)通过环境变量,但是临时生效

指定动态库路径并使其生效,然后再执行文件。

通过环境变量指定动态库所在位置:

export LD_LIBRARY_PATH=动态库路径

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qMcyOwDq-1679977310235)(Linux系统编程.assets/image-20220830215702559.png)]

当关闭终端,再次执行 a.out 时,又报错。

这是因为,环境变量是进程的概念,关闭终端之后再打开,是两个进程,环境变量发生了变化。

(2)修改配置文件,永久生效

要想永久生效(建议写入绝对路径):

  1. 需要修改 bash 的配置文件:vi ~./bashrc ,写入 export LD_LIBRARY_PATH=动态库路径 并保存。

  2. 修改后要使配置文件立即生效:. .bashrc 或者 source .bashrc 或者重开终端让其自己加载。

  3. 这下再执行 a.out 就不会报错了。

(3)移动动态库(不推荐)

拷贝自定义动态库 到 /lib (标准 C 库所在目录位置)

(4)配置文件法(最难)

sudo vi /etc/ld.so.conf

② 写入动态库绝对路径保存

sudo ldconfig -v 使配置文件生效

./a.out 成功 — 使用 ldd a.out 查看

4. 工作原理

静态库: GCC 进行链接时,会把静态库中代码打包到可执行程序中。

动态库: GCC 进行链接时,动态库的代码不会打包到可执行程序中。

程序启动之后,动态库会被动态加载到内存中,通过 ldd 命令检查动态库依赖关系。

如何定位共享文件呢?

当系统加载可执行代码的时候,能够知道所依赖库的名字,但是还需要知道绝对路径。对于 elf 格式的可执行程序,是由 ld-linux.so 来完成的,它先后搜索 elf 文件的 DT_RPATH 段 --> 环境变量 LD_LIBRARY_PATH --> /etc/ld.so.cache 文件列表 --> /lib/,/usr/lib 目录找到库文件后将其载入内存。

5. 区别

静态库

优点:

  • 静态库被打包到应用程序中,加载速度快
  • 发布程序无需提供静态库,移植方便

缺点:

  • 消耗系统资源,浪费内存
  • 更新、部署、发布麻烦

动态库

优点:

  • 可以实现进程间资源共享(共享库)
  • 更新、部署、发布简单
  • 可以控制何时加载动态库

缺点:

  • 加载速度比静态库慢
  • 发布程序时需要提供依赖的动态库

参考资料:
https://www.bilibili.com/video/BV1fy4y1b7TC/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=12c90255e5a0009cd588cada10859bd5
https://www.nowcoder.com/study/live/504

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CMD中dos命令

1 Ctrl R 2 有关某个命令的详细信息,请键入 HELP 命令名 ASSOC 显示或修改文件扩展名关联。 ATTRIB 显示或更改文件属性。 BREAK 设置或清除扩展式 CTRL C 检查。 BCDEDIT 设置启动数据库中的属性以控制启动加载。 CACLS 显示或修改文件的访问控制列表(ACL)。 CA…

第十一届“泰迪杯”数据挖掘挑战赛第四场赛前指导直播预告

为推广我国高校数据挖掘实践教学,培养学生数据挖掘的应用和创新能力,增加校企交流合作和信息共享,提升我国高校的教学质量和企业的竞争能力,第十一届“泰迪杯”数据挖掘挑战赛(以下简称挑战赛)已于2023年3月…

【MySQL】一文彻底搞懂 Redo-log 为什么要两阶段提交?

【MySQL】一文彻底搞懂 Redo-log 为什么要两阶段提交? 文章目录【MySQL】一文彻底搞懂 Redo-log 为什么要两阶段提交?两阶段提交的过程是怎样的?为什么需要两阶段提交?两阶段提交有什么问题?事务提交的方式——组提交两…

day1 计算机组成与结构考点汇总

一、重点知识点 计算机硬件组成、运算器、控制器奇偶校验码、循环冗余校验码、海明码指令系统:指令操作数寻址方式、CISC和RISC、指令流水线的计算存储系统:分级存储、局部性原理、cache、主存编址计算、磁盘输入输出技术:程序查询方式、中断…

解构同为科技(TOWE)工业连接器的配置和应用

如今,在各行各业作业生产中,都能看到工业连接器、插头插座的身影,它能够传输高速、高容量和高精度的信号和电力,具有防水、防尘、抗震动、抗干扰等特性,被广泛应用在工业控制、通讯、医疗、交通、航空、军事等领域&…

OTA(Over-the-air programming)是什么?

OTA(Over the air-programming)是什么? ‒ 是指将新软件,固件,设置,加密密钥更新无线发布到手机,机顶盒等设备的方式。 ‒ 对于固件而言,由于安装在诸如ROM,EPROM和flash memory等的…

初始 CSS 基础

专栏简介: 前端从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1. CSS 是什么 2. 基本语法规范 2. 引入方式 2.1 内部…

新六级通关训练

词汇题(55道) 1. You should carefully think over_____ the manager said at the meeting. A. that B. which C. what D. whose 1.选C,考察宾语从句连接词,主句谓语动词think over后面缺宾语,后面的宾语从句谓语动…

从GPT-4、文心一言再到Copilot,AIGC卷出新赛道?

业内人都知道,上一周是戏剧性的,每一天,都是颠覆各个行业,不断 AI 化的新闻。 OpenAI发布GPT-4、百度发布文心一言、微软发布Microsoft 365 Copilot 三重buff叠加,打工人的命运可以说是跌宕起伏,命途多舛了…

太敢说了,编程如果这么自学,培训班都得倒闭,直接省去上万元的学费

写了20多年的代码,之前做过阿里的高级架构师,在技术这条路上跌跌撞撞了很多,我今天分享一些我个人的自学方法给各位。现在在网上报个正经点的班得花几千块钱,线下就更夸张,都是万元起步,我的这些学习方法如果你能用好&…

Unity 使用Asset Studio查看apk包内资源

unity打包之后,想要查看包内图片,音频等资源,这时候我们就可以用到Asset Studio(以前叫Unity Studio,老软件已经不行了) 注意:界面中的Size大小为字节(bytes、B) 界面如…

【Azure 架构师学习笔记】-Azure Data Factory (5)-Managed VNet

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Data Factory】系列。 接上文【Azure 架构师学习笔记】-Azure Data Factory (4)-触发器详解-事件触发器 前言 PaaS服务默认都经过公网传输, 这对很多企业而言并不安全,那么就需要对其进行安全改…

关于微信小程序安装npm的过程,从下载到小程序内部安装完成

1.先从官网下载nodejs 网站为Node.js (nodejs.org),选择左边第一个2 然后一直next,选默认就行 选择自己喜欢的路径我的是D:\nodejs-v18.12.1 3 下载完成后,先在安装文件夹中新建两个文件夹 node_cache node_global 4 配置一下环境变量&…

第十三届蓝桥杯国赛 C++ C 组 Java A 组 C 组 Python C 组 E 题——斐波那契数组(三语言代码AC)

目录1.斐波那契数组1.题目描述2.输入格式3.输出格式4.样例输入5.样例输出6.数据范围7.原题链接2.解题思路3.Ac_code1.Java2.C3.Python1.斐波那契数组 1.题目描述 如果数组 A(a0,a1,⋯.an−1)A(a_0,a_1,⋯.a_{n-1})A(a0​,a1​,⋯.an−1​)满足以下条件, 就说它是一个斐波那契…

VSCode 安装Flutter 教程

第一步 下载flutter https://docs.flutter.dev/development/tools/sdk/releases#windows 第二部 配合环境变量 1、官方文档的是Linux的下载方法 export PUB_HOSTED_URLhttps://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn2、window的…

Mac中罗技logi options+下载问题

Mac中罗技logi options下载问题 捣鼓了一个上午解决了下载不了 页面卡住 windows中直接下载配置就行 Mac中: 1.到官网下载 logi options 官网下载 尝试安装 这块是卡在这下不了的 找到next.json文件(mac上文件管理直接搜索就行) 或者 find…

凤凰架构-周志明

一.演进 服务架构演进史 架构并不是被发明出来的,而是持续演进的结果。 原始分布式时代 UNIX 的分布式设计哲学 Simplicity of both the interface and the implementation are more important than any other attributes of the system — including correctness,…

物联网--Zigbee协议(二):Zigbee协议架构以及数据帧结构

上一篇整理了关于Zigbee协议的一些基础知识,接下来主要讨论Zigbee协议的架构,希望通过这篇文章能够帮助小伙伴们更好地理解Zigbee协议,废话不多说,进入正题吧。 文章目录一、Zigbee协议架构二、Zigbee协议的数据帧结构总结一、Zig…

92年程序员发帖晒薪资称自己很迷茫,网友:老弟你可以了

当下,是一个“向钱看,向厚赚”的社会。快节奏的生活下,家庭、工作各方面压力很容易使年轻人陷入迷茫和焦虑。 与其他行业相比,程序员的高薪让人羡慕。那么,对于那些真正达到这么多收入的人来说,他们是怎么…

Redis缓存优化

数据库在用户数量多,系统访问量大的时候,系统性能会下降,用户体验差。1.缓存优化作用:1.降低数据库的访问压力2.提高系统的访问性能3.从而提高用户体验实现思路:1.先查询缓存2.如果缓存有数据,直接返回3.如…