Linux的库文件
目录
概述:
静态库:
静态库概述:
静态库的制作
共享库(动态库)
共享库概述
动态库制作
动态库临时生效
动态库长期生效
动态库的升级
位置无关代码
概述:
库文件一般就是编译好的二进制文件,用于在链接阶段同目标代码一块生成可执行文件,或者运行可执行文件的时候被加载,以遍调用库文件中的某段代码。

动态链接都是索引的.so文件,静态链接都是压缩打包的.a文件。
库文件和可执行文件相比:
- 相同点:两者都是编译好的二进制文件
- 不同点:库文件没法直接执行(直观上看,他的源代码中没有main函数,而只是一些函数模块的定义和实现,没有运行的入口主函数,所以库文件没法直接执行)。
我们的程序开发,无论是运行的时候,还是编译,链接的时候,一般都需要借助一些库来实现他们的功能,而很少直接通过程序的源代码生成完全独立的可执行文件。
静态库:
静态库概述:
静态库实际上就是一些目标文件的(一般是以.o结尾)的集合,静态库一般是以.a结尾,只用于链接生成可执行文件阶段。
具体来说,以c程序为例子,一般我们编译程序源代码的时候过程大致是:
- 以.c为后缀的源文件经过编译生成.o文件的目标文件
- 以.o为后缀的目标文件经过链接生成最终的可执行文件。
我们可以在链接的时候直接链接.o的目标文件,也可以将这些.o文件打包集中起来,统一链接,而生成的打包集成了所有.o文件,也就是静态库。
静态库只在程序连接的时候时候,连接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中,一旦链接完成生成可执行文件之后,执行程序的时候就不再需要静态库了。
由于每一个静态库的应用程序都是需要拷贝所用到的函数的代码,所以静态库链接生成可执行文件会比较大,多个程序运行的时候占用的内存空间比较大,(每个程序在内存中都有一份复制的静态库代码),但是由于运行的时候不用从外部动态加载额外的库了,速度会比共享库快。
静态库的制作
实例:假设在实际工作中设计了两个算法,但是需要卖给其他公司使用,为了保护公司的知识产权是不能将源代码交给其他公司的,这样我们可以将两个算法封装或者打包到一个静态库中。
假设实现这两个算法的函数为func1()和func()2。
新建一个头文件hello.h,在hello.h中对两个函数进行声明:
编写一个简单的程序“hello.c”
将hello.c编译生成.o文件
gcc -c hello.c -o hello.o使用ar命令(ar是archive的意思)将hello.o文件打包成一个静态库文件libhello.a
ar rcs libhello.a hello.o注意:
- 如果需要将多个.o文件打包成文件库,则在命令行后边填写所有.o文件的名字即可
- 生成的库的名字必须是libxxx.a格式(注意:这里是尽量最好使用lib开头的格式,因为其他格式的编译方式是不一样的)
编译参数:<rcs>
r:表明将模块加入到静态库中,c表示创建静态库,s表示产生索引
使用nm命令查看库文件中包含的符号:nm libhello.a
使用 ar -t 命令查看静态库是由那些.o文件组成的:ar -t libhello.a
编写一个带有主函数的程序main.c,并且在main.c中调用静态库中的func1和func2函数:
现在所有文件下都在同一个目录下,没法直接体现出来静态库的作用。
在IO_file_test目录下新建一个static_lib_test目录进行测试将文件移动到下边设备树结构。(这里是一个比较常用的目录结构,但是为了方便测试三个文件都放在一个文件目录下即可)
解释:
include目录下是.h文件
lib里边是链接的静态库文件
src里边是.c文件
编译:
gcc main.c -L../lib -lhello -I../include -o main编译解释:
-L指向的是链接的静态库路径
-l(小L)是静态库的命称(去掉lib之后的)
-I(大i)链接存放.h文件的路径
编译现象:
在静态库的概述中会标红的地方提到了(一旦链接完成生成可执行文件之后,执行程序的时候就不再需要静态库了),所以这时删除掉libhello.a文件后程序仍然可以执行。
共享库(动态库)
共享库概述
共享库也叫做动态库。
静态库缺点:
- 内存消耗大;(假设一个静态库的大小为1M,当两千个程序都用到这库将消耗掉2G内存)
- 当静态库中的代码优化的时候,所有调用该静态库的程序需要重新编译,这样太过与麻烦。
动态库特点:
- 动态库在程序编译的时候并不会被链接到目标代码当中,而是在程序运行的时候才被载入。
- 不同的应用程序如果调用相同的库,那么在内存中里只需要有一份共享库的实例,规避了空间浪费问题。
- 动态库在程序运行的时候才能被载入,也解决了静态库对程序的更新,部署和发布页带来的麻烦。用户只需要更新动态库即可,增量更新。
动态库制作
参照静态库目录下创建三个文件如下:内容和静态库的也相同
![]()
编译链接生成.o文件

将编译好生成好的hello.o编译编译生成动态库:gcc -shared -fPIC -o libhello.so hello.o
注意:
- -shared:表明是使用的共享库
- -fPIC:表明生成与位置无关的代码、
- 动态库后缀为.so
- 动态库格式libxxx.so
- 如果还有其他链接的.o文件,直接在hello.o后边加上,用空格隔开

使用nm命令查看一个库文件中包含的符号: nm libhello.so

对照静态库测试目录制作动态库目录格式:

将上边共享库目录的文件对应拷贝到共享库测试目录里边如下:

进行编译:gcc main.c -L../lib -lhello -I../include -o main

但是如果直接执行的话,编译器会爆出一个错误。
错误的主要意思是在加载的时候打不开动态库文件,但是注意:动态库在在程序执行的时候会被加载。
这是因为在Linux中启动一个ELF格式的二进制可执行文件会自动启动和运行一个program loader(程序加载器:用来加载一些库)。对于Linux系统,这个loader的名字是ld-linux.so.X(X是版本号)。这个loader启动后会load所有的其他本程序的要使用的共享函数库。动态库与静态库不同,在执行文件的阶段需要加载动态库文件,而加载的动态库文件需要在指定位置或者添加在环境变量中,才能正确的加载动态库文件。
动态链接库的查找先后顺序:
- LD_LIBRARY_PATH环境变量中的路径
- /etc/ld.so.cache缓存文件
- /usr/lib和/lib
动态库临时生效
可以临时将libhello.so所在的路径追加到环境变量LD_LIBRARY_PATH中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/book/Desktop/IO_file_test/shared_lib_test/lib
冒号后边跟是自己的动态库路径。
修改完成之后我们可以使用echo $LD_LIBRARY_PATH查看环境变量被修改的值

注意: 在终端使用expert命令来修改当前环境变量的值,只是对当前会话临时生效,如果切换到一个新的会话窗口或者新的终端,关闭当前会话窗口都会失效。

动态库长期生效
- 修改系统启动配置文件,将export命令添加到启动文件当中
设置环境变量:
1.打开 vim ~/.bashrc 文件
2.在文件末尾添加一行
export LIBRARY_PATH=$LIBRARY_PATH:库文件的路径(如果需要删除环境变量,需要在~/.bashrc中删除环境变量后,关掉终端,重新启动终端才能生效)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/book/Desktop/IO_file_test/shared_lib_test/lib
3.重新加载配置文件 source ~/.bashrc
- 将动态库文件拷贝到/usr/lib或者/lib目录下(一般不采用这个种方式,因为这样会污染系统,并且不方便项目迁移)
- 修改/etc/ld.so.conf文件
动态库的升级
引入:
在实际工作当中,我们可能经常需要对动态库的板本进行升级,假如原来的库为libhello.so,那么升级完以后还需要保留每一个旧的板本,动态库的名字就不能重复,但是程序在加载的时候只加载libhello.so文件,解决:所以我们可以对每一个板本的动态库文件进行不同的命名,然后在新建立软链接,链接需要使用的实体库即可。

根据动态的命名规则,我们可以将动态库的第一个板本命名为:libhello.so.1.0.0,然后创建软连接
ln -s libhello.so.1.0.0 libhello.so


假设我们在原来的库上增加了某些接口我们可以将新库的版本名命名为libhello.so.1.1.0,删除原来的软连接文件,并重新创建软链接文件到该文件。



位置无关代码
位置无关代码(PIC:position-independent code),也被称为地址无关代码,是指源代码被编译成二进制文件(可以是执行文件也可以是某个库文件),编码方式也和位置(地址)无关。
程序在运行的时候是需要被加载到物理内存上运行的,但是操作系统为了方便每个进程进行内存管理,使用虚拟内存技术,每一个进程运行时都会得到4G的虚拟内存。这个虚拟内存可以认为每个进程任务自己认为自己有4G的空间,着只是每个进程认为的,但是实际上,在虚拟内存对应的物理内存上,可能只对应一点点的物理内存,实际用了多少内存,就会对应多少物理内存。
使用静态库和动态库编译生成的可执行文件在运行时候在内存上的加载方式:

如果使用了静态库编译可执行程序,每个函数在内存中的位置(地址)在编译完成以后就已经决定了。
但是共享库(动态库)是在可执行程序执行的时候加载进去的,动态编译后的函数的调用地址是自动计算出来的,这就是与位置无关的代码。
下边是找到的一个资料对位置无关代码的验证:

在64为机器上可以运行32位的指令。

相关文章:
Linux的库文件
目录 概述: 静态库: 静态库概述: 静态库的制作 共享库(动态库) 共享库概述 动态库制作 动态库临时生效 动态库长期生效 动态库的升级 位置无关代码 概述: 库文件一般就是编译好的二进制文件&…...
JAVA Web 学习(五)Nginx、RPC、JWT
十二、反向代理服务器——Nginx 支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量,其占用内存少、并发能力强、能支持…...
Python编程的十大神奇依赖库
Python是一门广受欢迎的编程语言,其生态系统丰富多彩,拥有许多令人惊叹的依赖库,可以帮助程序员们在各种领域中创造出令人瞠目结舌的应用。在这篇文章中,我们将探讨Python编程的十大神奇依赖库,它们像魔法一样…...
Java类的继承
XHTMLMapper继承 XWPFDocumentVisitor: 由于endVisitTableCell是抽象方法,XHTMLMapper中必须要实现; existErr()子类是否重写都是自由的; public abstract class XWPFDocumentVisitor<T, O extends Options, E extends IXWPFM…...
【DC渗透系列】DC-4靶场
主机发现 arp-scan -l┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:6b:ed:27, IPv4: 192.168.100.251 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.100.1 00:50:56:c0:00:08 …...
开源软件全景解析:驱动技术创新与行业革新的力量
目录 什么是开源 开源的核心 开源软件的特点 为什么程序员应该拥抱开源 1.学习机会: 2.社区支持: 3.提高职业竞争力: 4.加速开发过程: 5.贡献和回馈: 开源软件的影响力 开源软件多元分析: 开源…...
目标检测及相关算法介绍
文章目录 目标检测介绍目标检测算法分类目标检测算法模型组成经典目标检测论文 目标检测介绍 目标检测是计算机视觉领域中的一项重要任务,旨在识别图像或视频中的特定对象的位置并将其与不同类别中的对象进行分类。与图像分类任务不同,目标检测不仅需要…...
跟着cherno手搓游戏引擎【20】混合(blend)
抽象: Renderer.h: #pragma once #include"RenderCommand.h" #include "OrthographicCamera.h" #include"Shader.h" namespace YOTO {class Renderer {public:static void Init();static void BeginScene(OrthographicCamera& …...
leetcode 3.无重复字符的最长字串(滑动窗口) (C++)DAY2
文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示…...
Android Build 依赖项
在项目中的Build.Gradle文件中dependencies代码块中添加指定依赖项。 有三种不同类型的依赖项 本地模块依赖项 implementation project(:mylibrary)这个mylibrary 必须在 settings.gradle 中使用的库名称相同 本地文件依赖项 implementation fileTree(dir: libs, include:…...
SpringMVC精简知识点
SpringMVC 数据格式化基本数据类型和字符串自动转换特殊数据类型和字符串自动转换 验证及国际化应用实例注意事项和使用细节注解的结合使用数据类型转换校验核心类-DatBinder取消某个属性的绑定中文乱码解决处理json和HttpMessageConverter<T>作业布置SpringMVC文件上传自…...
如何写好论文——(17)如何用批判性思维检阅文献
在写论文的时候,往往需要引用很多文献资料,作为论点来证明我们的研究目标是合理的。在讨论和结论中,我们往往也需要引用很多的文献资料和我们自己的研究结果放在一起,来证明我们的研究结果是有意义的。所以在选择文献资料的时候&a…...
git将项目的某次签入遴选(Cherry-Pick)另一个项目
需求:将项目Product,分支feature/platform,签入959294ce6b75ee48c5cb22c46d7398654628a896,遴选到项目BRP,分支dev 第一步:使用原签入生成patch文件(git format-patch -1 <commit_hash>&a…...
开源节点框架STNodeEditor使用
节点,一般都为树形Tree结构,如TreeNode,XmlNode。 树形结构有其关键属性Parent【父节点】,Children【子节点】 LinkedListNode为链表线性结构,有其关键属性Next【下一个】,Previous【上一个】,…...
算法每日一题: Nim游戏 | 找规律
哈哈,大家好,我是星恒,今天的每日一题真开心,连做了3天牢,终于ak了一道,太不容易了 这道题其实就是找规律,刚开始我还以为是动归,但是列举了不少例子之后,发现有自己直接…...
分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别
分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别 目录 分类预测 | Matlab实现GAF-PCNN-MATT格拉姆角场和双通道PCNN融合多头注意力机制的分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现G…...
Dockerfile保留字
目录 一、Dockerfile保留字是什么? 二、Docker构建流程 1. 从基础镜像运行容器 2. 执行指令并修改容器 3. 提交新的镜像层 4. 基于新镜像运行新容器 5. 执行下一条指令 6. 循环执行指令 7. 所有指令执行完成 三、保留字 1. FROM 使用基础镜像作为起点 2.…...
Linux的7个运行级别
目录 1、有那7个运行级别? 2、那么如何查看运行级别呢? 3、那么我想临时切换运行级别? 4、那么我想修改配置文件中的运行级别呢? 1、有那7个运行级别? 0:停机状态。系统默认运行级别不能设置为0,否则系统不能正常启动&a…...
Linux期末总复习( 详解 )
文章目录 一、选择题二、填空题三、简答题四、操作题 一、选择题 1.在创建Linux分区时,一定要创建( D )两个分区 A. FAT/NTFS B. FAT/SWAP C. NTFS/SWAP D.SWAP/根分区 2.在Red Hat Linux 9 中,系统默认的…...
【Linux系统化学习】进程等待
目录 进程等待 进程等待的必要性 进程等待的方法 wait方法 等待一个进程(阻塞等待) waitpid方法 任意等待多个进程(阻塞等待) 父进程获取子进程的退出信息 非阻塞轮询等待 进程等待 进程等待的必要性 之前讲过,子进程退…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...








