Linux基础IO - 软硬链接 | 动静态库

news2024/11/27 8:00:41

之前的文章中我们讲述了软硬链接中有关软连接的知识,本文中将继续讲述硬链接部分的知识,并且讲述一下动静态库的相关内容。

硬链接

硬链接本质上就是在当前目录建立一个新的文件名与指定文件inode的关系。

每当我们在当前目录下建立一个硬链接就会让文件属性中的硬链接数增加1:

Linux中除了使用rm指令来删除还可以使用unlink指令进行删除:

硬链接的应用场景

从上图中我们也可以看到新建了一个普通文件之后,它的硬链接数为1,只有一组文件名与inode的映射关系,这个非常好理解:当新建了一个目录之后可以发现它的硬链接数是2,这是为什么呢?进入一个新的目录进行查看,可以看到在里面有两个文件 . 和 .. 通过之前的学习我们知道 . 表示当前路径 .. 表示上级路径,而我们又知道目录本身就是一个文件,综上所述就可以得到正确的答案:一个新建目录的硬链接数之所以为2,一是因为自己本身是一个文件,二是因为在目录的内部有一个文件指向了自己,从上面两者拥有相同的inode就可以看出。

很显然因为在这个目录中还有两个目录,这两个目录中都有着 .. 文件,再加上创建目录之后的两个硬链接数,这样当前目录的硬链接数就变为了4。

 那么如果我们给目录建立硬链接的话会发生什么,进行尝试,会发现无法建立硬链接。操作系统允许自己建立硬链接,而不允许用户建立硬链接,为了防止造成环路问题。

文件的三个时间

一个文件被操作时有三个时间 Modify、Change、Access:

Change表示对一个文件属性修改的时间:

Modify表示对一个文件内容进行修改的时间,很显然当我们对文件的内容进行修改的时候其属性也会发生变化 :

 Access表示一个文件最后被访问的时间:

当我们多次打开文件并查看其访问时间会发现一段时间内该信息不会修改。 在较老的版本每次被访问就会进行记录,由于文件属性定期要更新到磁盘上,这会到时系统IO的频率要增加,增加系统交互的成本。

动静态库

C/C++的标准库我们一直都在使用,在VS中安装的开发环境,就是在安装编译软件,安装开发语言配套的库和头文件;头文件提供方法说明,库提供实现方法,头和库是有对应关系的,是要组合在一起使用的;头文件在预处理阶段就引入的,链接的本质就是链接库。 使用编译器时的语法提醒的本质就是不断地在包含的头文件中进行搜索,自动提醒是依赖头文件来的。

动态使用,os作为后缀,静态库使用.a作为后缀;一般库都有前缀与后缀例如:libc.a、libc-2.17.so库的名称就是去掉前缀和后缀和版本号剩下来的那个,前面这两个就是c库的静态库和动态库。

动静态库的设计和操作

直接编译

这里我们编写了几个简单的声明和实现分离的文件,让其表示我们将要使用的头文件:

我们很自然的就可以使用gcc指令将其编译为可执行程序,得到这样的结果:

通过链接方式生成可执行文件

这里创建otherPerson目录表示库的其他使用者,mylib存放对应的头文件和C文件,但是若是不想将源文件直接暴露出去,可以将源文件经过预处理编译汇编等变为.o可重定位二进制文件,在这个.o文件中已经包含了函数实现的方法,把.o文件和.h文件都拷贝至使用者目录下,再将main.c文件同样编译至.o文件,然后将这三个.o文件进行链接得到可执行程序:

这样就可以在不暴露源代码的情况下,让程序能够运行。

通过静态库文件生成可执行文件

直接把.o文件给别人有些不太优雅,因此我们将库文件进行打包,使用 ar -rc libmymath.a *.o 指令将.o文件进行打包,同时可以对库中的信息进行查看。

然后,我们将对应的.h和.a文件拷贝至main文件的位置进行编译:

可是,会发现无法直接使用这个库。当我们有了一个库,接下来要将库引入我们的项目,必须让编译器找到头文件+库文件,这个库属于第三方库编译器不认识这个库,我们要想办法让编译器认识。

所以,在当前目录下我们可以使用 gcc -o mytest main.c -L. -lmymath 指令来使用动态库进行编译。

-L 指定库路径
-l 指定库名 库的名字如上所述需要去掉前缀和后缀和版本号
测试目标文件生成后,静态库删掉,程序照样可以运行

 但是给用户的时候一般不是按我们上图的样子的,我们新建一个include目录和lib目录,将之前生成的.h文件和.a文件分别放入其中,将这两个目录达成一个压缩包,然后将这个压缩包拷贝给使用者。

然后使用编译指令进行编译,此时需要注意:

gcc -o mytest main.c -I./include -L./lib -lmymath

-I 指定头文件的路径

-L 指定库路径
-l 指定库名 库的名字如上所述需要去掉前缀和后缀和版本号

将静态库拷贝到系统搜索路径下生成可执行文件

将include这种的头文件拷贝到系统搜索头文件的搜索路径下;将lib中的库文件拷贝到系统库文件的搜索路径下;

然后应为这是我们自己编写的第三方的库,因此需要我们把库的名字告知编译器,才能正常的运行。 

动态库的生成和使用

通过指令 gcc -fPIC -c myadd.c mysub.c 生成.o文件,这种方法生成的文件与生成静态库中生成的文件有所不同。fPIC:产生位置无关码(position independent code)

然后再生成对应的动态库:gcc -shared -o libmymath.so  *.o 我们就得到了动态库。 与上面同样拷贝到使用者的目录下,通过如上所示的编译却发现又出现了问题:

上述去情况是由于我们只将库在哪里告诉了编译器,却没有告诉系统。运行的时候.os没有在默认路径下,所以OS找不到。静态库,它的链接原则是将用户所使用的代码直接拷贝到目标可执行文件中,而动态库不会。

运行动态库生成可执行文件的方法

使用 ldd 指令可以查看可执行文件所依赖的库文件,可以看到虽然我们编译成功了,但是没有找到我们编写的第三方库。

  1. 由环境变量指定的目录(临时方法)(LD_LIBRARY_PATH)将我们自己编写的库文件的路径添加到该路径中然后再查看,就能够查找到,并且能够执行:
  2. 建立软链接方法 把我们自己的动态库文件在/lib64中建立一个软链接 
  3. 配置文件方法 配置/etc/ld.so.conf.d/,ldconfig更新 在这个目录下新建一个 .conf 文件,然后把动态库所处的位置拷贝到这个文件中,在对配置进行更新即可。

第三方库的使用

  1. 需要指定头文件,和库文件
  2. 如果没有默认安装到系统gcc/g++默认搜索路径下,用户必须指明对应的选项,告知编译器:a、头文件在哪里;b、库文件在哪里;
  3. 将我们下载下来的库和文件,拷贝到系统默认路径下 --- Linux下安装库;对任何软件而言安装和卸载的本质就是拷贝到系统特定的路径下。
  4. 如果我们安装的库是第三方的(语言,操作系统接口)库,我们要正常使用,即使是已经全部安装到了系统中,gcc/g++必须用 -l 指明具体库的名称。

动静态库的理解 - 加载

静态库链接形成的可执行程序本身就有静态库中对方法的实现。

动态库加载问题

我们使用动态库时,形成可执行程序,没有直接将动态库拷贝到程序里,找到了库中程序的位置然后,把可执行程序中的外部符号被替换为了库中的具体地址。然后将可执行程序加载到物理内存中,就变为了一个进程,拥有了PCB、地址空间和维护映射关系。同样在代码区中也有了对应关系。当程序执行到printf方法时,发现没有该方法,但是进程结合操作系统就能知道这个程序依赖于动态库,然后就会去在系统中寻找,找到之后同样会加载到内存中,并且映射地址空间的共享区中。回到调用printf的地方,此时就直接回跳转到库中的方法:1234处,并执行,然后再返回继续执行。

当又有了进程B,同样要进行与A一样的操作,当想要访问printf时,操作系统发现已经加载了,可以直接将库映射到地址空间中,即可完成库中代码与自己的代码相互跳转的过程,因此动态库也被叫做共享库。库可能会很大,但同时不一定会全部加载到地址空间中。

库中地址的理解

之前在编写动态库的时候,讲过一个与位置无关码。我们知道地址实际上只会有两种地址,相对地址和绝对地址。绝对地址在起始参照物发生变化之后就会发生变化,它的位置就无法再被知晓了。但是相对地址只要相对参照物不发生变化,就能够找到其地址。静态库由于直接将库拷贝到了可执行程序中因此,使用绝对地址编址没有问题,但是这不能用在动态库中,动态库必定面临着一个问题:不同的进程,运行程度不同,需要使用的第三方库也是不同的,注定了每个进程的共享空间中空闲位置是不确定的;因此需要使用相对编址,动态库中的所有地址都是偏移量,默认从零开始。当一个库真正的被映射进地址空间的时候,它的起始地址才能真正的确定。只要我们知道了动态库在地址空间中的真正起始地址,再加上需要的方法对应的偏移量,就能够得到需要的方法。

与位置无关码:动态库中地址,都是偏移量。

一些其他问题的验证

当静态库与动态库都存在时优先会使用动态库:

当动态库缺失时,只有静态库时:

会发现这样的情况,生成的可执行文件要比纯动态库要大,而且在查询动态库的时候,没有显示我们自己编写的库,因此可以推断,该文件动态链接了其他的库并且静态链接了我们自己编写的库。

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

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

相关文章

C++11多线程之条件变量

文章目录 一、关于多线程的同步二、初始条件变量三、关于条件变量的例题四、生产者消费者模型 一、关于多线程的同步 //函数被调用,分配相应的栈帧,进行现场保护void func(char c) {char filename[20] {};sprintf(filename, "test%c.txt",c)…

Fiddler Response私人订制

在客户端接口的测试中,我们经常会需要模拟各种返回状态或者特定的返回值,常见的是用Fiddler模拟各种请求返回值场景,如重定向AutoResponder、请求拦截修改再下发等等。小编在近期的测试中遇到的一些特殊的请求返回模拟的测试场景,…

《变形金刚7》票房大跳水!特效敷衍?剧情单薄?汽车人的未来在哪里?

《变形金刚:超能勇士崛起》 6.11(上映第3天) 单日票房8200万 6.12(上映第4天) 单日票房2173万 6.13(上映第5天) 单日票房1700万 说实在的,真没想到《变形金刚7》日票房会如此大幅…

高压放大器在铁电材料中的应用研究

铁电材料是一种具有特殊磁电性能的材料,包括压电陶瓷、磷酸铁钠陶瓷、氧化锌压电陶瓷等。这些材料在电力、电子、机械等领域有广泛的应用,如超声波发生器、声纳、压力传感等。其中,高压放大器在铁电材料中有着重要的应用。 一、高压放大器的基…

完美搭建一个vue3+ts项目(一篇文章搞定你的所有疑惑)

目录 一、创建vite项目 二、启动vite项目 三、处理一些配置问题 四、增加工程化插件 1、安装sass 2、安装vue-router 3、安装pinia 4、安装element-plus 5、安装axios 6、设置路径别名,将相对路径改为绝对路径 一、创建vite项目 1、在一个文件夹下通…

Vision Pro:为什么空间音频是AR的绝杀武器?

Apple Vision Pro,不仅仅是苹果全新的重磅品类,而且在它身上也融合了苹果过去几乎所有新技术,比如空间音频就是其中一个例子。 苹果表示,Vision Pro中空间音频可以很好的应用在:影视节目、游戏内容、3D空间照片、3D空…

金融风控项目实战-银行信用卡流失预测模型_基于ANN神经网络_金融培训_论文科研_毕业设计

业务背景 根据央行公布的数据显示,全国性银行信用卡和借贷合一卡的发卡量增速从2017年同比增速26.35%的高点逐年下降,截至2020年同比增速降至4.26%。银行信用卡发卡增速明显放缓的背景下,预防老客户流失的问题变得愈发重要。 假设一家消费信…

pytest+allure

知识点1: 1、测试结果信息阅读 passed表示通过,有个简写. failed表示失败,有个简写F 2、命令行参数 -h:帮助 -version:版本信息 3、测试用例命名规则: 测试函数必须以test开头 测试类必须以Test开头…

我为开放原子全球开源峰会助力:共建开源之梦

我为开放原子全球开源峰会助力:共建开源之梦 6月11日,以“开源赋能,普惠未来”为主题的2023开放原子全球开源峰会开幕式暨高峰论坛在北京成功举办。 开源的力量与魅力 开源是当今软件行业中不可忽视的力量,它为技术的快速发展和…

入职滴滴和字节的2 年里,我感觉忒真实了……

引言 先简单交代一下背景吧,某不知名985的本硕,17年毕业加入滴滴,之后跳槽到了头条,一直从事软件测试相关的工作。之前没有实习经历,算是两年半的工作经验吧。 这两年半之间完成了一次晋升,换了一家公司&…

Ubuntu如何安装vmtools?

虚拟机-安装VMware Tools 然后在Ubuntu中找到设备中的VMware Tools,将这个文件来复制到桌面上去。 选择提取到此处 可以看到桌面上多了一个VMware Tools的文件夹 使用cd命令进入桌面上的这个VMware tools的文件夹 使用sudo ./安装命令 对vmware-tools-distrib文件夹…

政企市场,「观望」AI大模型

数据安全等“刚需”下,私有化成为政企市场的准入门槛,然而私有化下,行业模型局限性尚未可知,加之信创化等因素,厂商仍需取长补短,为政企客户提供全方位的解决方案。 作者|斗斗 编辑|皮爷 出品|产业家 政…

采用UWB定位技术开发的室内定位系统源码

UWB精准定位系统源码 UWB是什么? UWB(Ultra Wideband)超宽带技术是一种全新的、与传统通信技术有极大差异的通信新技术。它不需要使用传统通信体制中的载波,而是通过发送和接收具有纳秒或纳秒级以下的极窄脉冲来传输数据,实现精准定位。 技术…

一名高水平的程序员,为什么面试总是失败?

目录 场景1 场景2 场景3 1 从发现和分析问题方面准备。 2 从linux命令和日志层面分析问题的步骤。 1 事先准备很重要 2 面试开始是自我介绍,这时要表露出,自己解决过redis,dubbo等组件的线上问题 3 一旦开始说第一个组件层面解决过的问题时&…

Django高级扩展之文件上传

文件上传是一个比较常用的网站功能,在服务器端,Django会使用一个叫作request.FILES的对象来处理上传的文件。 目录 存储路径 创建存储目录 配置settings.py 上传单文件 配置url 上传文件模板 视图方法 显示上传页面 上传文件处理 上传效果 1.…

盘点五种最常见加密算法!

大家好,我是Martin。 今天,就给大家来盘点一下最常见的5种加密算法。 大家平时的工作中,可能也在很多地方用到了加密、解密,比如: 用户的密码不能明文存储,要存储加密后的密文 用户的银行卡号、身份证号…

2024年天津农学院专升本专业课参考书目

天津农学院2024年高职升本科拟招生专业参考书目 天津农学院专升本专业课参考教材(我校不提供专业课参考教材) 人力资源管理专业参考教材: 1、《人力资源管理实用教程》 (第2版),吴宝华,北京大学出版社 2、《人力资源…

运维(SRE)成长之路-第3天 文本处理三剑客之 grep

1.命令作用以及参数详解 grep: 全局搜索正则表达式并打印行(Global search REgular expression and Print out the line)作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行模式:由正则表达式字…

GitHub Copilot 最全安装、使用

GitHub Copilot 最全安装、使用教程 一、温馨提示 GitHub Copilot 目前为止可以免费试用一个月,但是试用的前提是必须要绑定银行卡,因为后续会自动扣费,所以请注意试用结束日期,自己定好闹钟关闭订阅。 订阅价格为每月10美刀&a…

【Pinia 状态管理篇】Vite + Vue3 组合式 API 模式下的 Store 数据处理

文章目录 Pinia 状态管理一、 Pinia 安装与使用1.1 安装1.2 注册 pinia 实例到全局1.3 创建一个 Store1.4 组件内使用 Store 二、Pinia 核心概念展开学习Store 的定义和使用2.1 State2.2 Getter2.3 Action 附:1. 什么是魔法字符串? Pinia 状态管理 一、 …