【Linux内核系列】:文件系统收尾以及软硬链接详解

news2025/3/16 21:19:45

🔥 本文专栏:Linux
🌸作者主页:努力努力再努力wz

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

💪 今日博客励志语录世界上只有一种个人英雄主义,那么就是面对生活的种种失败却依然热爱着生活

内容回顾

那么在之前的学习中,我们知道了操作系统是如何管理我们未打开的文件,我们知道文件的数据是存储在磁盘上的,而操作系统要管理磁盘上的所有数据,那么必然在操作系统中建立一个磁盘的逻辑映射,那么其中磁盘中的数据是保存在盘面上的一圈一圈的磁道的扇区当中,那么我们可以将该立体空间中每一个扇区按照一个线性的一维数组来进行一个排列,那么该一维数组就是磁盘的逻辑结构,其中该一维数组中的每一个元素就是一个扇区,其中为了区分不同位置的扇区,那么我们就得给扇区一个唯一的标识符,那么我们扇区在一维数组对应的数组下标便是扇区的编号从0到n分配给不同位置的扇区,而该编号也称之为LAB地址,那么当我们有了扇区的LAB地址之后,由于LAB地址是逻辑地址而不是扇区在实际的磁盘中的物理地址,而我们需要定位扇区在磁盘中真实的物理地址,而定位其在磁盘中的位置则需要该位置对应的磁头以及磁道和扇区这三个坐标,所以有了LAB地址之后,操作系统会采取特定的算法将LAB地址映射转换该位置的三个坐标即可

那么扇区是我们磁盘存储的基本单元,那么磁盘读写数据是以扇区为单位来进行读写,但是由于扇区的存储的内容量一般只有512字节,而现在的文件的大小动辄就是几十甚至上百个GB,而磁盘读取的速度取决于机器运动的次数,那么以扇区为单位读写必然io的速度就会很慢,所以不同的文件系统会采取将多个扇区给组合形成该磁盘读写的最小单元,以EXT4文件系统为例,那么它是以8个扇区为一组作为一个逻辑块,那么磁盘一次读写的数据量就是4KB,那么这样就提高了io的效率,所以在文件系统所定义的逻辑块的视角下,那么原本的一维线性数组的每一个元素便不再是一个个扇区而是逻辑块,所以给一维数组的元素个数以及每个元素的编号就会发生变化

其中由于磁盘的数据量很大,那么操作系统管理如此庞大的数据,那么采取的策略就是分区,其中将该一维线性数组分成不同的区域来进行管理,但是即使将其分区,那么每一个区的数据量依然很大,所以会进行更为细致的划分,将每一个分区在划分成不同的分组,那么其中管理好整个磁盘就是管理好该分区的每一个分组以及不同的分区,那么这就是对前置知识的回顾,如果感到陌生或者说好奇其中的细节的话,可以阅读之前的文章

★★★ 本文前置知识:

文件系统


重新理解文件

那么了解了磁盘的一个逻辑结构以及操作系统管理磁盘的一个方式之后,那么我们知道文件是由两部分所构成,分别是文件的属性以及文件的内容,那么对于文件的属性来说,操作系统则是会为其定义一个inode结构体,其中封装了该文件的各个属性字段其中就包括文件的权限以及文件的创建时间以及最近修改时间,那么inode数据则是保存在inode区域中的特定的逻辑块中,而对于文件的内容,那么保存文件内容的逻辑块则是和保存文件属性的逻辑块位于不同的区域,所以在Linux下,文件的属性以及内容是分开来管理,而其中对于inode结构体中还有一个非常重要的字段便是一个索引数组,那么该数组则是保存了该文件的内容的数据块的索引,那么意味着有了inode结构体,那么我们既能获取文件的属性也同时能够获取文件相关联的数据块
在这里插入图片描述

所以现在我们就便能理解当我们创建以及一个文件时,系统会做什么

创建文件

那么文件是有内容+属性这两部分构成,当我们创建一个文件时,那么意味着首先就得定义该文件对应的inode结构体,而既然要创建inode结构体,那么我们就得为该文件分配一个空闲的逻辑块来保存该inode结构体的数据,所以系统会到分区的各个分组中,首先会查看该分组的gbt字段,因为gbt字段保存了该分组的整体的逻辑块的使用情况,其中记录了该文件的多少inode逻辑块被使用,多少inode逻辑块是剩余空闲,那么接着再去查看inode表,那么inode表是一个位图结构,其中每一个比特位对应特定位置编号的逻辑块,那么该比特位的值就表示该逻辑块是否被使用,那么为inode分配好一个逻辑块之后后,接下来就是对inode结构体的相关属性进行一个初始化,那么这就是系统创建文件的一个过程

删除文件

那么文件是由属性和内容两部分构成,那么删除一个文件必然就是要删除这两部分数据,而我们知道文件本质就是由保存属性的inode结构体以及保存文件的内容的数据块所构成,而我们的inode结构体中内部有一个索引数组能够找到该文件关联的数据块,那么也就是意味着删除一个文件,我们只需要找到该文件的inode结构体,那么即可获取该文件的全部内容,而获取文件的inode结构体的方式那么就是得需要知道保存该inode结构体的数据的逻辑块的编号,所以一旦获取到inode编号之后,那么我们根据该编号确定该inode对应的逻辑块是在哪一个分组中,然后该分组的块表则记录那些逻辑块被使用哪些逻辑块未被使用,而inode表则是记录了哪些inode结构体被使用哪些未被使用,所以我们获取到inode结构体的编号之后,那么意味着也能同时获取到数据块的编号,接着就只需要将块表以及inode表中对应位置的比特位设置为0即可,无需要覆盖inode块以及数据块的内容,然后更新gbt,这样就逻辑上完成了对文件的删除

所以删除一个文件,意味着会更新相应的块表以及inode表等属性,而不会直接采取覆盖数据块以及对应的inode块,那么也就意味着其实删除一个文件本质上是可以恢复的,但是恢复的过程其实比较复杂还要涉及到专业的工具,并且文件系统的格式化其实也就是在重新初始化对应的分区的每个分组的块表以及inode表等属性,也不会覆盖所谓的数据块以及inode块


那么对于其中的文件的删除,过程道理想必大家都懂,那么关键是我怎么获取目标文件的inode编号呢,我们在Linux上删除文件,我们知道是输入rm指令,而其中我们输入rm指令删除目标文件都是后面直接输入的是删除目标文件的文件名,而不是输入的是其inode编号,但是系统也确实成功删除了目标文件,那么这又是怎么回事呢?

那么我们删除一个文件核心肯定是需要文件的inode编号,那么既然我们只需要输入文件名就可以达到删除的效果,那么只能说明一点,那么就是系统有我们该文件名到inode编号的映射,那么要说清楚这点,那么就得重新来认识一下我们的目录了

目录文件

那么我们之前在Linux的学习中,我们知道可以输入mkdir指令来创建一个目录,那么我们也知道目录本质上其实也是一个文件,有着自己的属性,那么既然是一个文件,那么不用说,它肯定也有一个inode结构体在其中的一个特定的分组当中,那么它的inode结构体肯定也记录其相应的属性比如权限以及创建时间等,那么同理它也一定有一个索引数组指向其关联的数据块,那么我们对于普通文件来说,其inode关联的数据块就是其文件内容,那么对于我们目录文件来说,它也有自己所属的数据块,那么对于目录文件来说,它的数据块保存的是什么内容呢?

答案就是它的数据块保存的就是其目录当中子目录以及子文件的文件名到inode编号的映射,那么每一个数据块也就是目录项保存的都是这个key-value模型的一个映射关系的内容,那么也就是说,我们查找一个目标文件的inode编号,那么就需要到目标文件所处的目录中的目录项中去匹配找到对应的映射关系,获取到其对应的inode编号,所以这就是我们为什么同一个目录下,不能有重名文件的文件的原因

所以我们有了目录文件的概念之后,那么我们就得对之前上文所说的创建文件以及删除文件的过程进行一个完善,那么对于其中创建文件,我们知道会为该文件定义一个inode结构体,然后为在分组中为其分配一个未被使用的逻辑块来保存inode的数据,而其中对于其所处的目录文件中,那么目录文件的数据块也就是目录项中也会添加该文件关于文件名到其文件编号的映射

同理对于删除文件来说,那么首先我们得获取该文件的inode编号,那么我们就得从其所处的目录中的目录项中找到其对应的inode编号,也就是要获得其所处目录的目录项里面的内容,那么我们也得递归的去该目录的上一级目录中得到该目录的inode编号,而我们的文件是以树状的数据结构来组织的,那么其中整个文件系统的根节点便是根目录,而其inode编号是已知的,例如在EXT4文件系统中它对应的inode编号是2,那么我们要得到目标文件的文件编号,我们只需要得到该目录的绝对路径,也就是从根目录到该目标文件的路径,那么系统就会从根目录往下逐层解析,从根目录开始,扫描其目录项中寻找下一级目录的映射关系获取到其inode编号,那么再同理递归到下一级的目录当中扫描其目录项获取其下一级的目录或者文件的inode编号直到达到目标文件

那么由此便能解释之前的问题,为什么我们rm指令输入目标文件的文件名而不是inode编号,也能够删除目标文件

那么如果我们输入删除的目标文件带有绝对路径,那么就是按照上述过程,解析该绝对路径找到目标文件的inode编号然后删除

但是如果是相对路径的话,那么系统会获取到该进程的内核的环境变量中的CWD字段,那么该字段保存了所处的工作目录的inode编号,那么从该目录文件的目录项找到目标文件的inode编号从而删除

而至于进程的内核的环境变量中的CWD字段为什么能够直接获取到所处的目录的inode编号,那么则和dentry缓存有关,因为我们知道从根目录开始解析到目标文件,这其中的过程要涉及扫描每一个目录的目录项的映射关系,那么时间代价就很大,所以dentry就是一个数据结构记录了每一级目录的inode编号,那么我们进程切换目录的时候会利用缓存来得到当前目录的inode编号从而更新CWD,而无需解析整个路径

软链接

那么有了目录以及目录项的概念之后,那么我们其中便可以引入软链接

那么第一个问题:

软链接是什么

那么我们在解释其原理之前,我们先来看看软链接长什么样子,那么我们可以输入该指令来创建软链接一个指向test.c文件的名为soft的软链接

ln -s [目标文件或目录] [软链接名称]

那么创建完之后软链接之后,我们再来使用ls -l 指令来查看一下当前目录下的所有子目录以及文件的属性,

在这里插入图片描述

我们发现创建的软链接本质上其实也就是一个文件,那么既然它是一个文件,那么它肯定就由文件的内容和属性所构成,也就意味着其一定有对应的inode结构体,那么我们可以输入ls -li查询inode编号
在这里插入图片描述

根据结果我们发现其软链接以及该软链接指向的目标文件test.c的inode编号是不同的,那么说明其有自己独立的inode结构体以及其相关联的数据块,那么其独立的inode结构体肯定存储其相关的属性,那么其相关联的数据块那么存储的是什么内容呢?

那么我们可以输入cat指令来打印器软链接的文件内容到终端上
test.c文件内容:
在这里插入图片描述

cat内容:
在这里插入图片描述

那么我们发现软链接打印的内容竟然就是其指向的目标文件的内容

软链接怎么做到的

那么我们软连接本身有一个独立的inode结构体以及相关联的数据块,软连接本身的数据块存储的内容便是目标文件的路径,所以当我们输入cat指令来访问到软链接的时候,那么首先会得到软链接的inode编号并且识别到该文件的类型,然后从inode编号中获取其关联的数据块,而其数据块存储的内容便是其目标文件的路径,那么接着系统会解析这个路径得到目标文件的inode结构体从而间接访问到目标文件的数据块,然后打印的是指向的文件的文件内容,所以我们的软链接和我们c语言的指针其实非常的像,那么指针的本质其实就是一个变量,只不过该变量的内容就是指向的目标数据的地址,而同理我们的软链接,也是一个文件,只不过内容保存的是指向的目标文件的路径

注:软链接指向的目标文件一定要存在,如果不存在,那么我们软连接保存的内容是无效的,那么此时该软链接的状态就是悬浮的就类似于我们指针不能为空,不然解引用就会出错

软链接的应用场景

那么在我们Windows下我们的一个可执行文件的成功执行需要编译各种配置的源文件,那么可执行文件和其源文件会封装到一个文件夹在特定的盘的特定路径下保存,那么我们运行这个可执行文件,那么我们就得知道其路径,但是我们用户通常不需要记住每一个可执行文件它保存的路径在哪里,而是通过桌面的快捷方式点开即可运行,那么其实这个快捷方式本质上就是一个软链接,那么它内部记录了可执行文件的路径,那么打开该快捷方式其实本质上就是解析其路径然后运行目标的可执行文件即可

所以学习了Linux之前,相信大家都有过这么的经历,那么就是删除一个文件,很多人以为我将快捷方式放到回收站删除即可那么现在我们知道了,你删除的快捷方式其实本质上是删除了一个软链接,那么该程序的可执行文件以及源文件其实没有任何影响

硬链接

那么有软连接,我们Linux还有硬链接的存在,那么它的作用其实和软连接是差不多的

那么我们先来看看在Linux下我们是如何创建我们的硬链接:

     ln 目标文件 硬链接
     

硬链接是什么

我们在认识硬链接是什么之前,我们还是先来看一下硬链接长什么样子吧,那么我们假设在当前目录下创建一个test.c文件,然后创建一个名为hard的硬链接来指向该test.c文件,然后首先我们还是输入ls -l指令来查看我们当前目录下的子目录以及文件属性,我们发现当前目录下有我们的硬链接文件以及指向的目标文件test.c
在这里插入图片描述

然后我们再来输入ls -li来查看该该目录下的文件的inode编号,我们发现硬链接文件以及指向的目标文件的inode编号是相同的
在这里插入图片描述

下一步我们再来输入cat指令来打印我们的硬链接的文件的内容时
test.c内容:
在这里插入图片描述
cat 硬链接:
在这里插入图片描述
我们发现其硬链接打印的内容竟然还是指向的目标文件test.c的文件内容

硬链接怎么做到的

那么我们知道硬链接文件是和其指向的目标文件的inode编号相同,那么说明其共享一个inode结构体,并其硬链接和指向的目标文件是共享inode结构体和其关联的数据块,那么当我们创建一个硬链接的时候,那么会在该硬链接所处的目录中添加一个新的映射,也就是该硬链接的文件名到inode编号的映射,所以当我们访问该硬链接的时候,那么其实本质上就是直接访问了其指向的目标文件的inode结构体,所以打印的内容就是目标文件的内容

并且有了硬链接的概念之后,那么我们输入ls -l指令所展示的文件的属性中,其中拥有者以及所属组和其他后面那个数字便是该文件的硬链接数,而我们创建一个普通文件,那么该文件的硬链接数初始化是1,因为它所处的目录文件的目录项会指向它,而对于目录文件来说,则是2,是因为它所处的目录文件会有一个指向其子目录的目录项,并且对于该目录的目录项来说,那么它也有一个目录项,也就是文件名为".“指向自己的inode的映射,同时还有一个文件名为”…“指向其上级目录的映射,而对于根目录来说,其”.“与”…"都指向自己
在这里插入图片描述

注:一般不建议创建指向目录的硬链接,因为我们知道了目录的目录项中有自己以及所处子目录的引用,而如果你在当前所处的目录下创建一个比如其上级目录的应用,那么我们在解析路径的时候就会陷入循环导致崩溃,所以硬链接使用的很少,一般都选择软链接

所以当我们删除一个文件的时候,我们要确定是否彻底删除清理该文件的属性以及内容的数据的时候,我们系统其实首先会得到其文件的硬链接数,然后减一,如果该硬链接数不为0的话,那么意味着还有其指向该文件的inode结构体,所以不会清空该文件的inode结构体以及内容数据,但是如果为0,那么该文件不再被需要,那么则会删除该文件的inode结构体以及其相关联的数据块
在这里插入图片描述

结语

那么这就是本篇文章关于文件系统以及软硬件链接的全部内容了,那么这篇文章也就是我们Linux文件系统的收官了,那么文件系统也就此完结撒花告一段落啦,那么恭喜你看到这里,成功的翻阅了文件系统这道大山🎆🎆,当然,对于我这几篇文章来说,肯定是不可能全部覆盖到所有的Linux文件系统的知识,只是覆盖了大部分并且其中最高频的知识,那么其中文件系统跟Linux其他的内容比如进程之间的联系,那么又是说来又是话长,那么我也考虑要不要出一期文章来解析,总之感谢你的耐心观看!

那么我下一期的文章便是动静态库的实现,那么我会持续更新,希望你能够多多关注支出,如果本篇文章有帮组到你的话,那么还请你多多三连加关注哦,你的支持就是我创作的最大的动力!
在这里插入图片描述

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

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

相关文章

视频理解之Actionclip(论文宏观解读)

配合解读代码解读 1.研究背景 1. 视频行为识别的重要性 视频行为识别是视频理解领域的核心任务之一,旨在通过分析视频内容来识别和分类其中的人物行为或活动。这一任务在多个领域具有重要的应用价值,例如智能监控、人机交互、自动驾驶、医疗健康等。随…

navicat16 升级到 navicat17 之后原来的连接找不到了 mac用户

版本16的路径 注意把对应的路径改成自己的用户名 /Users/自己的用户名/Library/Application Support/PremiumSoft CyberTech/Navicat CC/Common/Settings 版本17的路径 /Users/自己的用户名/Library/Containers/com.navicat.NavicatPremium/Data/Library/Application Suppor…

Altium Designer——CHIP类元器件PCB封装绘制

文章目录 PCB封装组成元素:焊盘的属性 SS34肖特基二极管SMA(DO-214AC)封装绘制资料:步骤:1.绘制焊盘:用到的快捷键:资料: 2.绘制丝印:用到的快捷键:资料: PCB封装组成元素…

【一起来学kubernetes】12、k8s中的Endpoint详解

一、Endpoint的定义与作用二、Endpoint的创建与管理三、Endpoint的查看与组成四、EndpointSlice五、Endpoint的使用场景六、Endpoint与Service的关系1、定义与功能2、创建与管理3、关系与交互4、使用场景与特点 七、Endpoint的kubectl命令1. 查看Endpoint2. 创建Endpoint3. 编辑…

《AI浪潮中的璀璨新星:Meta Llama、Ollama与DeepSeek的深度剖析》:此文为AI自动生成

《AI浪潮中的璀璨新星:Meta Llama、Ollama与DeepSeek的深度剖析》:此文为AI自动生成 引言:AI 大模型的群雄逐鹿时代 在科技飞速发展的当下,AI 大模型领域已成为全球瞩目的焦点,竞争激烈程度堪称白热化。从 OpenAI 推出…

LVGL移植到6818开发板

一、移植步骤 1.lv_config.h 配置文件启动 framebuffer 2、lv_config.h 配置文件关闭SDL 2.修改main.c 去掉SDL输入设备 3.修改Makefile 文件启动交叉编译 去掉警告参数 去掉SDL库 4.交叉编译代码 make clean #清空 ⭐ 必须要清空一次再编译! 因为修改了 lv_con…

UE4-UE5虚幻引擎,前置学习一--Console日志输出经常崩溃,有什么好的解决办法

有些差异 这么牛逼的引擎,居然有这种入门级别的问题,一触发清理,大概率(80%)会崩溃 无论虚幻5还是UE4都有这个问题,挺烦人的 实在忍不了了,这次,今天 就想问问有什么好的处理方法么?&#x…

(全)2024下半年真题 系统架构设计师 综合知识 答案解析01

系统架构设计师第二版教程VIP课程https://edu.csdn.net/course/detail/40283 操作系统 下列选项中不能作为预防死锁措施的是 。 A. 破坏“循环等待"条件 B. 破坏“不可抢占”条件 C. 破坏“互斥”条件 D. 破坏“请求和保持”条件 答案:C 解析&…

Linux系统之less命令的基本使用

Linux系统之less命令的基本使用 一、less命令介绍二、less命令的使用帮助2.1 less命令的帮助信息2.2 less命令主要选项解释 三、less命令的基本使用3.1 查看文件内容3.2 结合管道使用 四、注意事项 一、less命令介绍 在Linux和Unix类操作系统中,文件浏览是一项常见的…

【微知】plantuml在泳道图中如何将多个泳道框起来分组并且设置颜色?(box “浏览器“ #LightGreen endbox)

泳道分组并且着色 分组用 box和endbox ,颜色用#xxx,标注用"xxx" box "浏览器" #LightGreen participant "浏览器1" as Browser participant "浏览器2" as Browser2 endboxparticipant "服务端" as …

C#生产型企业ERP系统管理软件PCB行业ERP进销存MRP管理系统BOM管理

背景 本软件为为苏州某生产型电子科技企业开发的ERP管理软件。 功能说明 希哲管理系统v1.0是一款在流览器上使用的企业管理软件,使用上与客户端版的优势是: 1.安装更新部署方便,只需服务器部署了软件,其它客户端的用户无需安装&am…

文件系统 linux ─── 第19课

前面博客讲解的是内存级文件管理,接下来介绍磁盘级文件管理 文件系统分为两部分 内存级文件系统 : OS加载进程 ,进程打开文件, OS为文件创建struct file 和文件描述符表 ,将进程与打开的文件相连, struct file 内还函数有指针表, 屏蔽了底层操作的差异,struct file中还有内核级…

射频前端模块(FEM)的基本原理与架构:从组成到WiFi路由器的应用

射频前端模块(FEM)的基本原理与架构:从组成到WiFi路由器的应用 一、FEM是什么? 射频前端模块(Front-End Module, FEM)是无线通信系统中负责处理射频信号的核心组件。它将多个关键电路集成在一个模块中,包括功率放大器(PA)、低噪声放大器(LNA)、射频开关(Switch)、…

qemu分析之 KVM_EXIT_MMIO

基于qemu-2.8.1 address_space_rw 函数作用 这是QEMU内存子系统的核心函数,负责分块处理跨MemoryRegion的内存读取操作。主要场景包括: 处理跨越多个MemoryRegion的连续内存读取区分RAM直接访问与MMIO设备模拟处理不同位宽(1/2/4/8字节&am…

OSI 七层网络模型

文章目录 OSI 七层模型应用层表示层会话层传输层网络层数据链路层物理层 TCP/IP 四层模型应用层传输层网络层数据链路层 TCP/IP 特点OSI 和 TCP/IP 两者关系通信过程及相关协议常用协议及端口号常用协议分类参考链接 OSI 七层模型 七层模型,亦称OSI(Ope…

虚拟电商-数据库分库分表(二)

本文章介绍:使用Sharding-JDBC实现数据库分库分表,数据库分片策略,实现数据库按月分表 一、Sharding-JDBC使用 1.1.准备环境 步骤一:分库分表sql脚本导入 创建了两个数据库:chongba_schedule0 和chongba_schedule1…

进程间通信--匿名管道

进程间通信介绍 进程间通信目的 数据传输:一个进程需要将它的数据发送给另一个进程资源共享:多个进程之间共享同样的资源。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件&…

C#opencv 遍历图像中所有点 不在圆范围内的点变为黑色,在圆范围内的保持原色

C#opencv 遍历图像中所有点 不在圆范围内的点变为黑色,在圆范围内的保持原色 安装 Install-Package OpenCvSharp4 Install-Package OpenCvSharp4.Windows 普通实现 using System; using System.Collections.Generic; using System.Linq; using OpenCvSharp; // 添加OpenCV引用…

基于SSM + JSP 的图书商城系统

基于SSM的图书商城 网上书城、图书销售系统、图书销售平台 |Java|SSM|HTML|JSP| 项目采用技术: ①:开发环境:IDEA、JDK1.8、Maven、Tomcat ②:技术栈:Java、…

【漫话机器学习系列】133.决定系数(R²:Coefficient of Determination)

决定系数()详解 决定系数()是回归分析中用于评估模型拟合优度的一个重要统计指标。它表示自变量(特征变量)能够解释因变量(目标变量)变异的程度,取值范围为 [0,1] 或 (−…