Linux之静态库和动态库
目录
一、前言
二、对于库的理解
三、静态库
四、动态库
五、动静态库的加载
一、前言
在之前,我们讲了静态库和动态库,详情请跳转:静态库和动态库
下面我们将从工程师的角度,去了解静态库和动态库的形成过程,以及实现它们的制作。并且了解如何将自己的库交给别人,让别人也可以使用。
二、对于库的理解
Linux的库一般分为动态库和静态库:
静态库:库文件以 .a 为后缀,程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
动态库:库文件以 .so 为后缀,程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
gcc 在编译时默认使用动态链接,链接动态库,而如果想生成静态链接,我们需要在末尾带上 -static。
而我们知道,程序编译链接的最后,其实就是将各种 .o 可重定位目标二进制文件包括 main 函数的 .o文件,与所包含的 .h 文件全部链接起来,形成可执行程序。所以,这是不是就意味着,用户真正需要的库文件其实是 .o 文件,设计者可以不用将源文件提供给用户,而直接将.o和.h文件提供给用户,以供用户链接。这样不仅方便,而且能够保护源码。这样可以吗?
如下图,在该目录下,我们只有.h和.o文件,没有这些文件的源码。那么能编译成功吗?

编译结果如下:

我们发现,编译出的可执行程序能够运行。
但是如果存在很多.c文件呢?难道我们要把几千个.c文件全部编译成.o在加上头文件全部一个一个提供吗?那样太过于麻烦,为了让用户更好的使用库,我们就有把所有的.o文件打成一个包,给对方提供一个库文件。
所以,库中包含了多个.o文件。
三、静态库
我们可以使用 ar 命令(把所有的.o打包起来),来制作一个静态库。比如:我们要打包二中所讲到的.o文件:
ar -rc libexe.a myadd.o myprintf.o

当然,我们也可以写一个Makefile来快速制作一个库。

output:而我们要交付库,实际上要把库文件 .a 以及匹配的头文件都交付给用户,而output就相当于一个发布的过程。

好了,那么静态库我已经制作好了,且已经发布了,那么我们来使用一下自己制作的库。首先,我们将库拷贝到 mylib 目录下去使用。

但是,当我们编译时,却出错了:

gcc在编译时,找不到头文件!!!
解决方法:编译器搜索头文件时默认在当前目录下搜索,在系统默认指定路径下搜索。虽然此时的mylib在当前路径下,但是头文件太深了,编译器找不到头文件,所以我们需要给gcc指定路径。如下:使用选项 -I 告诉编译器头文件所在路径。

问题又来了,gcc找不到库函数的实现。我们在形成可执行程序的时候,库文件要使用的话也要知道库所在的路径在哪里,系统的默认路径是/lib64,而这是我们自己制作的库,不在里面。所以我们要带上 -L。告诉库的路径在哪里。因为该路径下可能有多个库,所以我们还要使用 -l 选项,加上库名字去掉前缀和后缀 .a。

如上图,我们编译并且运行成功了。
总结:
-I:指明头文件的搜索路径
-L:指明库文件的搜索路径
-l:指明要链接哪个库,带上库的名称(去掉前缀和后缀)
四、动态库
首先我们需要把库文件全部编译成.o文件,这里与静态库不同,需要带上选项 -fPIC,形成与位置无关码。我们还是以上面的文件为例:
gcc -fPIC -c myadd.c -o myadd.o
gcc -fPIC -c myprintf.c -o myprintf.o

动态库打包需要加上选项:-shared。
gcc -shared myprintf.o myadd.o -o lib.so

我们可以建立一个makefile,同时形成静态库和动态库。


然后我们发布:

接下来,我们就来使用一下我们自己制作的动态库。

下图中,我们编译成功,且形成了可执行程序。 
但是,当我们运行可执行程序时,却失败了:

因为我们的lib目录下,既有动态库,也有静态库,所以gcc在编译时默认使用的是动态库。可是,既然我已经指明了库所在的路径,那为什么在运行可执行程序时还会动态链接失败呢?
原因就是:那只是在编译时,告诉了gcc编译器动态库在哪里,然后编译成功且形成了可执行程序,如果你在编译时没有告诉库在哪,编译就不会成功,且不会形成可执行程序。而我们运行可执行程序是由操作系统加载到内存来运行的,运行时也需要告诉操作系统库在哪里。我们还没有告诉操作系统动态库在哪里呢!!!
解决方法:
1、添加到环境变量里:把库路径添加到环境变量LD_LIBRARY_PATH
比如:我的动态库所在路径为:/home/zdl/mylib/output/lib

但是我们自己定义的环境变量只是本次登录有效,如果想永久有效只能修改环境变量的配置,但是比较麻烦。想永久有效,我们还有其他的方法。
2、配置文件(/etc/ld.so.conf.d/):动态库进行对应搜索时可以采用自己定义conf文件找到动态库
直接在该路径 /etc/ld.so.conf.d/ 下创建一个以.conf为后缀的文件。

然后将动态库所在的路径添加到文件中即可。

最后,使用sudo ldconfig使文件生效。
3、建立软链接直接找到对应的库
可以将库的路径建立软链接到 /lib64/ 路径下。
五、动静态库的加载
静态库:静态库是直接将自己的代码和数据拷贝到可执行程序中,然后随可执行程序一同加载到内存中。它们相当于已经是一体的了。静态库的代码随可执行程序的代码一起加载到程序地址空间的代码区。
动态库:动态库可以和可执行程序分批加载。
动态库加上fPIC选项形成位置无关码,采用相对编址的方法,在程序链接时对应库当中的偏移量添加到可执行程序,运行时一旦库加载进来,经过地址空间映射,把库映射到地址空间之后,库也就具备了起始地址,通过偏移地址和起始地址这样就可以找到访问的函数。
具体过程:可执行程序在运行时,如果遇到某处代码需要调用库的方法,库的代码和数据就会加载到物理内存中,然后将你需要使用的方法通过页表映射到共享区。然后代码直接到共享区去找,再通过页表找到物理内存中的具体方法,使用完后,代码继续向后执行,如又遇到库里的方法,就再去找。

如果有多个进程需要使用同一个库,那么其他的进程可以直接通过页表和物理内存中的代码直接建立联系。所以动态库加载一次就可以被多个进程共同使用了。
而静态库可能有多个程序用了C库,加载到内存时,内存里可能会存在很多份重复的代码。而动态链接不会出现重复的代码,减少内存占用。
相关文章:
Linux之静态库和动态库
目录 一、前言 二、对于库的理解 三、静态库 四、动态库 五、动静态库的加载 一、前言 在之前,我们讲了静态库和动态库,详情请跳转:静态库和动态库 下面我们将从工程师的角度,去了解静态库和动态库的形成过程,以…...
erlang/OTP 平台(学习笔记)(三)
分布式 Erlang 借助于语言属性和基于复制的进程通信,Erlang程序天然就可以分布到多台计算机上。要问为什么,且让我们来看两个用Java或C这类语言写成的进程,它们运作良好并以共享内存为通信手段。假设你已经搞定了锁的问题,一切精…...
Spring整理-Spring框架中用了哪些设计模式
Spring框架广泛应用了多种设计模式,这些模式提高了框架的灵活性、可扩展性和可维护性。下面是在Spring框架中常见的一些设计模式: 单例模式(Singleton):用于在应用的整个生命周期内保持一个类的单个实例。在Spring中,Bean默认是单例模式。 工厂模式(Factory Pattern):…...
Poi实现根据word模板导出-图表篇
往期系列传送门: Poi实现根据word模板导出-文本段落篇 (需要完整代码的直接看最后位置!!!) 前言: 补充Word中图表的知识: 每个图表在word中都有一个内置的Excel,用于…...
windows或mac端口转发
摘要 在内网开发中,由于出于公司安全考虑,部分IP192.168.0.100访问只能针对固定IP192.168.0.200开放,此时我需要通过我的电脑192.168.0.300去访问,由于未对我电脑IP192.168.0.300授权,导致我访问不到,此时…...
Linux工具-搭建文件服务器
当我们使用linux系统作为开发环境时,经常需要在Linux系统之间、Linux和Windows之间传输文件。 对少量文件进行传输时,可以使用scp工具在两台主机之间实现文件传输: rootubuntu:~$ ssh --help unknown option -- - usage: ssh [-46AaCfGgKkMN…...
深入理解@DubboReference与@DubboService【三】
欢迎来到我的博客,代码的世界里,每一行都是一个故事 探索Dubbo的核心:深入理解DubboReference与DubboService【三】 前言DubboService注解基本概念使用示例高级特性 DubboReference注解基本概念使用示例服务调用流程 最佳实践注解的最佳使用方…...
linux主机的免密登录
实现linux主机之间的相互免密登录 在进行远程登录的时,服务器和主机间进行认证阶段分为: 基于口令认证(不安全,易被抓包拦截获取) 客户机连接服务器时,服务器将自己的公钥返回给客户机 客户机会将服务器的…...
Git常用命令和QA(网摘)
主要内容 常用命令git checkout --orphan 分支与 git checkout -b 分支区别git如何创建一个新的空白分支branchgit开发分支本地分支合并远程分支git remote prune origingit log如何退出?如何退出git log或git commit模式git log如何退出git commit 的退出 git强制p…...
PHP AES 加密示例
PHP中实现AES加密的一个基本示例涉及到使用openssl_encrypt函数。这个函数允许你使用不同的加密算法,包括AES。下面是一个简单的示例,展示了如何使用AES加密一个字符串。 首先,你需要确定几个关键的参数: 数据(Data&…...
第十九章:特殊工具与技术
第十九章:特殊工具与技术 对于很多程序员来说,他们很少会用到本章的介绍的内容。 一.控制内存分配 我们能够重载new和delete,但其实不是对new和delete的重载,只是对new和delete操作符后面的函数进行重载。 当我们使用一条new表…...
大数据深度学习卷积神经网络CNN:CNN结构、训练与优化一文全解
文章目录 大数据深度学习卷积神经网络CNN:CNN结构、训练与优化一文全解一、引言1.1 背景和重要性1.2 卷积神经网络概述 二、卷积神经网络层介绍2.1 卷积操作卷积核与特征映射卷积核大小多通道卷积 步长与填充步长填充 空洞卷积(Dilated Convolution&…...
RabbitMQ(九)死信队列
目录 一、简介1.1 定义1.2 何时进入死信队列?1.3 死信消息的变化1.4 死信队列的应用场景1.5 死信消息的生命周期 二、代码实现2.1 死信队列的配置步骤2.2 配置类2.3 配置文件2.4 生产者2.5 业务消费者2.6 死信消费者2.7 测试结果 三、总结四、补充4.1 启动报错 ineq…...
KEI5许可证没到期,编译却出现Error: C9555E: Failed to check out a license.问题解决
一、编译出现如下报错 二、检查一下许可证 三、许可证在许可日期内,故应该不是许可证的问题 四、检查一下编译器,我用的是这个,这几个编译器的区别其实我不太明白,但我把问题解决是选的这个 五、找到编译器的路径,去复…...
南京观海微电子----时序图绘制工具
Wavedrom 是一款功能强大且简单易用的文本转图表工具,被广泛应用于生成时序图、波形图等交互式波形。其特点在于使用简单的文本语法,使得开发人员能够以可视化的方式表示数字信号和时间序列数据。Wavedrom 的优势在于其高度灵活性和可扩展性,…...
Gin CORS 跨域请求资源共享与中间件
Gin CORS 跨域请求资源共享与中间件 文章目录 Gin CORS 跨域请求资源共享与中间件一、同源策略1.1 什么是浏览器的同源策略?1.2 同源策略判依据1.3 跨域问题三种解决方案 二、CORS:跨域资源共享简介(后端技术)三 CORS基本流程1.CORS请求分类2.基本流程 四、CORS两种…...
TS:.d.ts 文件 和 declare 的作用
1 declare 做外部声明1.1 声明外部类型1.2 声明外部模块1.2.1 解决引入资源模块报错1.2.2 跳过对第三方库的类型检查 1.3 声明外部变量1.4 声明外部命名空间(作用域) 2 .d.ts 文件做外部声明3 declare global {} 在模块中做外部声明 先说一下我对 .d.ts文…...
JavaScript-jQuery2-笔记
1.获取元素文本、属性、内部结构、表单中的值 获取标签中所夹的文本内容:text() 获取标签的属性值:prop(属性名) 获取表单元素的内容:如 文本框中的内容 val() 获取元素的内部html结构:html() 2.筛选选择器 筛选选择器࿱…...
设计模式之多线程版本的if------Balking模式
系列文章目录 设计模式之避免共享的设计模式Immutability(不变性)模式 设计模式之并发特定场景下的设计模式 Two-phase Termination(两阶段终止)模式 设计模式之避免共享的设计模式Copy-on-Write模式 设计模式之避免共享的设计模…...
mybatis核心配置文件介绍
mybatis核心配置文件 1. properties配置介绍 properties标签:加载外部的资源配置文件 属性:resource 指定要引入的配置文件路径 在核心配置文件中,通过:${key}方式引入外部配置文件的数据 jdbc.peroperties 的文件内容…...
SEO_详解SEO优化的完整工作流程与执行要点
<h2>SEO优化的重要性</h2> <p>在当前数字化时代,网站的可见度和流量直接关系到企业的市场竞争力。搜索引擎优化(SEO)作为提升网站在搜索引擎中排名的关键手段,其重要性不言而喻。SEO不仅能帮助企业吸引更多的自…...
Anaconda 被误删后抢救手册:零重装、10 分钟极速恢复
引言 作为 Python 开发者、数据分析师、AI 学习者的「必备工具」,Anaconda 凭借便捷的环境管理、海量预安装包,成为入门与进阶的首选。但很多人曾因误操作 —— 比如清理 C 盘时删掉anaconda3文件夹、卸载时选错路径、甚至误删系统环境变量 —— 导致co…...
sklearn分类指标实战:如何用precision_recall_curve优化你的模型效果
sklearn分类指标实战:如何用precision_recall_curve优化模型效果 在机器学习项目中,分类模型的评估往往比训练过程更考验数据科学家的专业素养。当你的模型在测试集上达到95%的准确率时,是否就意味着可以高枕无忧?现实情况往往复杂…...
BthPS3驱动技术指南:实现PS3手柄在Windows 11系统的蓝牙适配与优化
BthPS3驱动技术指南:实现PS3手柄在Windows 11系统的蓝牙适配与优化 【免费下载链接】BthPS3 Windows kernel-mode Bluetooth Profile & Filter Drivers for PS3 peripherals 项目地址: https://gitcode.com/gh_mirrors/bt/BthPS3 当你尝试将PS3手柄连接到…...
1999-2025.4汽车之家、懂车帝汽车配置信息数据库
汽车配置信息数据是连接汽车生产、销售、使用及后市场服务的核心纽带,对不同主体均具有不可替代的价值。对消费者可辅助决策,规避风险,对车企可指导研发,优化生产,对经销商可精准销售,提升转化,…...
M3U8 开发调试神器!m3u8live.cn轻量在线播放器高效解决流媒体开发痛点
在音视频开发、直播推流、点播平台搭建的日常工作中,M3U8 链接有效性验证、HLS 流播放调试是高频刚需。传统方案要么需要安装 VLC 等本地播放器进行繁琐的网络串流配置,要么第三方工具广告泛滥、兼容性差,甚至需要编写测试代码才能完成简单的…...
Python金融计算提速迫在眉睫!(仅剩3类未公开的底层优化手段,第3种已被高盛2023年专利覆盖)
第一章:Python金融计算提速迫在眉睫!(仅剩3类未公开的底层优化手段,第3种已被高盛2023年专利覆盖)高频回测、实时风险敞口计算与蒙特卡洛期权定价正面临Python原生执行效率的严峻瓶颈。当单次万标的风险因子矩阵运算耗…...
OpenClaw跨平台部署:Qwen3.5-9B在mac/Windows/Linux下的差异处理
OpenClaw跨平台部署:Qwen3.5-9B在mac/Windows/Linux下的差异处理 1. 为什么需要关注跨平台差异? 去年我在帮团队搭建自动化办公流程时,发现一个有趣的现象:同样的OpenClaw配置脚本,在同事的MacBook上运行流畅&#x…...
Spring_couplet_generation 结合微信小程序:春节活动创意应用开发
Spring_couplet_generation 结合微信小程序:春节活动创意应用开发 春节,是中国人最重视的传统节日。贴春联,更是家家户户辞旧迎新的重要仪式。但每年都买现成的春联,总觉得少了点新意和专属感。有没有一种方式,能让每…...
信息安全保障模型
信息安全保障模型是指导组织构建安全体系的理论框架。信息安全领域发展出了多个经典且广泛应用的安全模型。这些模型从不同维度阐述了如何实现“保护信息资产的机密性、完整性和可用性(CIA)”的目标。1. P2DR / PPDR 模型全称:Policy, Protec…...
