
🎬 个人主页:HABuo
📖 个人专栏:《C++系列》《Linux系列》《数据结构》《C语言系列》《Python系列》《YOLO系列》
⛰️ 如果再也不能见到你,祝你早安,午安,晚安

目录
📚一、软硬链接
📖1.1 硬链接
📖1.2 软链接
📚二、动静态库
📖2.1 静态库的定义及使用
📖2.2 动态库的定义及使用
📚三、动态库的加载
📚四、总结
前言:
前面我们认识了文件系统,从底层上理解了磁盘中怎么划分、怎么管理,有哪些属性,今天我们就在上篇博客的基础上继续深入学习,软硬链接的区别,动静态库的原理与制作!最后讲解一下动态库如何加载!
本章重点:
软硬链接是什么?有什么区别?动静态库是什么?如何自己定义动静态库,动态库是如何加载的!
📚一、软硬链接
在 Linux 系统中,链接(link)是一种为文件或目录创建额外名称的机制,主要用于文件共享和访问便捷性。链接主要分为两种类型:硬链接(hard link) 和软链接(symbolic link,又称符号链接)。
📖1.1 硬链接
硬链接:
—> 本质上是在同一个文件系统分区中
—> 给同一个文件(即同一个 inode)创建额外的文件名。
—> 每个硬链接都指向相同的 inode
—> inode 中存储着文件的元数据(如权限、所有者、时间戳)以及指向实际数据块的指针。
工作原理:
—> 文件系统通过 inode来唯一标识一个文件。每个文件至少有一个文件名指向其inode。
—> 当创建一个硬链接时,系统会在当前目录下新增一个目录项,该目录项关联到同一个inode编号
—> inode 中有一个字段 链接计数(link count),记录了有多少个文件名指向该 inode
—> 每增加一个硬链接,链接计数加 1
—> 删除一个文件名(即删除一个硬链接)时,链接计数减 1
—> 只有当链接计数变为 0 时,系统才会真正删除该文件的数据。
硬链接的特点:
—> 共享同一个 inode:所有硬链接完全平等,对任何一个链接的内容修改都会反映到其他链接
—> 不能跨文件系统:因为 inode 编号只在同一文件系统内唯一,硬链接必须位于同一分区
—> 不能对目录创建硬链接:出于防止循环引用和破坏文件系统树结构的考虑
普通用户不允许为目录创建硬链接(超级用户理论上可以,但强烈不建议)
—> 删除源文件不影响其他硬链接:只要还有一个硬链接存在,文件数据就依然保留
使用指令: ln 创建硬链接

📖1.2 软链接
软链接:
—> 软链接类似于 Windows 中的“快捷方式”
—> 它是一个特殊的文件,其中包含了指向另一个文件或目录的路径名
—> 当通过软链接访问文件时,系统会自动将其重定向到目标路
工作原理:
—> 软链接本身是一个独立的文件,拥有自己的 inode 和数据块
—> 它的数据块中存放的是目标文件的路径字符串(可以是绝对路径或相对路径)
—> 访问软链接时,内核根据存储的路径去解析目标文件
—> 如果目标文件被移动或删除,软链接就会失效(称为“悬空链接”)
软链接的特点:
—> 拥有自己的 inode:与硬链接不同,软链接的 inode 与目标文件的 inode 不同
—> 可以跨文件系统:因为存储的是路径,只要路径可达即可
—> 可以对目录创建软链接:这是常见的用法,例如 /etc/alternatives 机制或用户链接到常用目录
—> 链接大小取决于路径长度:软链接文件的大小就是它所指向的路径字符串的长度
—> 权限独立:软链接自身的权限通常为 rwxrwxrwx(对所有用户开放)
但实际访问时,最终由目标文件的权限决定(目标文件的权限起作用)
不过,软链接的权限可以被修改,但一般不影响访问
对软链接的权限修改会直接作用于目标文件吗?
实际上 chmod 作用于软链接时默认会改变目标文件的权限,除非使用 -h 选项
使用指令: ln -s 创建软链接

软硬链接的区别:
| 本质 | 同一个文件的多个目录项 | 存储路径的特殊文件 |
| inode | 与目标文件相同 | 独立的 inode |
| 跨文件系统 | 不可以 | 可以 |
| 链接目录 | 不可以 | 可以 |
| 目标删除后 | 文件数据仍然存在(只要还有硬链接) | 链接失效(悬空链接) |
| 链接计数 | 目标文件链接计数增加 | 不影响目标文件的链接计数 |
| 权限 | 与目标文件权限一致,通过 inode 共享 | 有自己的权限,但最终访问权限由目标文件决定 |
| 文件大小 | 不额外占用数据块空间(仅增加目录项) | 占用少量空间存储路径字符串 |
| 查看方式 | ls -l 第二字段显示链接数,ls -i 看 inode | ls -l 会显示箭头指向目标 |
📚二、动静态库
- 静态库(.a结尾): 程序在编译链接时就把库的代码拷贝到可执行程序
- 动态库(.so结尾): 程序运行时才去链接动态库的代码,动态库的代码是被共享的
libXXX.a(静态库)
libXXX.so(动态库)
动静态库是都是以lib开头的,静态库的后缀是.a,动态库的后缀是.so,并且动静态库的真实名称是去掉开头的lib,去掉后缀,中间剩余的就是动静态库的真实名称
—> 系统的库的路径是 /lib64
—> ldd 可执行程序,可以查看一个可执行程序运行所需要的共享库
—> file 可执行程序,可以查看一个可执行程序的链接方式
为什么需要动静态库?如果将我们的所写的代码方法提供给别人使用,你是不太情愿直接将源文件给其他人进行使用,所以有了库这种方式,即想办法将我们的源文件打包成库给其他人使用,即头文件.h + 库的方式
📖2.1 静态库的定义及使用
我们定义下述文件:




通过上面的实验想说明:
- 库文件就是.o文件的集合
- 想让别人使用你的库,必须将库文件和头文件一起给别人
制作静态库指令:
ar -rc libmymath.a mymath.o



上面报错的原因是找不到库,需要我们显示指定库路径,我们将头文件与库文件集体打包成一个文件夹,头文件也会发生找不到的错误解决办法类似:



📖2.2 动态库的定义及使用
整体的流程与上述类似,但指令有所差别,在这里我们只进行指令的讲解:
动态库的.o文件必须使用以下方式生成:
gcc -fPIC -c mymath.c
动态库打包必须使用以下方式:
gcc -shared mymath.o myadd.o … -o libmymath.so
但当你运行时就会发现报错:

原因:
你不是已经告诉了库文件,路径和库名称了吗?-你告诉了谁??gcc
当你把程序编译完,和gcc还有关系吗??没关系
程序运行起来,OS和shell也是需要知道库在哪里的!!
而你的库没有在系统路径下,OS无法找到!!
解决办法一:环境变量方式
$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/库路径
但是有缺陷,如果我们不将该环境变量放置到对应的环境变量的配置文件中,那么下次重新登陆shell时,就又恢复成原来的,就还需要再次导入!更新到对应的配置文件也比较麻烦,所以还有下面的几种方式
解决办法二:配置/etc/ld.so.conf.d/,ldconfig更新

解决办法三:建立软链接的方式

这是将软链接建立在当前路径下,当然建立在系统路径下也是可以的。
解决办法四:直接将库文件以及头文件导入到系统路径下(即安装)
📚三、动态库的加载
标题写的是动态库加载,静态库需不需要加载呢?答案是不需要的,在前面博客的学习中,我们就已经了解到静态库就是将对应的实现拷贝到我们的程序中,形成可执行以及加载到内存时完全和我们自己的代码编址是一样的,用的是绝对地址的方式!
动态库加载:
前面选项有个:fPIC ,产生位置无关码(position independent code)
什么是与位置无关码? 就是采用的相对位置,比如:我在你前面十米,而不是我在起点五十米!
整体流程见下图:

—> 动态库以位置无关码的方式编址存储在磁盘,但是起始地址尚未知
—> 当程序加载到内存成为进程,代码执行到printf时,就会去寻找定义
当然会通过部分标识使得进程知道,这个定义在某些动态库中,操作系统就会去加载这个动态库
—> 当动态库加载到内存通过页表映射到虚拟地址空间中的共享区时,该库也就天然的存在了起始虚拟地址
—> printf在自己的虚拟地址空间就可以直接跳转到共享区执行printf,通过页表找到对应的库中的实现
—> 执行完成之后返回到对应代码段我们程序的位置!
📚四、总结
本篇博客我们介绍了软硬链接、动静态库的制作与使用、以及动态库的加载。
小结以下: 软硬链接:
软链接:是独立文件,有独立的inode,以及文件属性,文件内容存储的是指向文件的路径!
硬链接:不是独立文件,通过新文件名与指向文件的inode建立某种联系,其中通过引用计数的方式控制文件的删除!Linux下的上级目录 .. 和当前目录 . 就是通过硬链接的方式实现的
动静态库:
静态库:以.a结尾,使用时是将对应的代码拷贝到我们程序的指定位置!
动态库:以.so结尾,使用时是通过地址方式跳转到库中的定义!
库的制作:库的本质就是.o文件的集合,打包时需将库文件与头文件一同打包,因为代码需要引用头文件!静态库打包指令:ar -rc 静态库生成.o文件使用指令:gcc -c。动态库打包指令:gcc -shared,并且动态库生成.o文件使用指令:gcc -fPIC -c。
动态库加载:采用与位置无关码的方式,整体流程见上图!

网硕互联帮助中心




评论前必须登录!
注册