【文件系统】软硬链接

目录

  • 1. 汇总 ext2 文件系统
  • 2. 文件名 与 inode 的关联
  • 3. 软硬链接
    • 3.1 理解硬链接
    • 3.2 理解软链接
    • 3.3 软硬链接的应用场景

1. 汇总 ext2 文件系统

在这里插入图片描述

  • 新建文件
    一个文件一定是在某个路径下创建的,有了路径,就能够知道该新建文件所在分区,然后再查 GDT,发现 inode 还没分配完,于是遍历 inode Bitmap 找到最近一位没有被使用的 inode 编号(即比特位为0), 再通过 inode Table 找到对应的 inode,把文件属性填充到 inode 中,如果文件中没有写入数据,那么文件的新建,到这一步就完成了。如果后续对文件写入数据,确定了写入数据的大小,接着根据 inode 编号找到文件所在分组,然后在 Block Bitmap 中分配足够的数据块,并且把这些数据块的编号填充到 inode 属性中,最后将数据写入对应的数据块。

  • 删除文件
    与新建文件相反。先根据 inode 找到文件属性,再根据其中的 block 数组,通过 Block Bitmap 映射,将所有数据块编号所对应的比特位置 0,再通过 inode Bitmap 映射到对应的 inode,将该比特位置 0 即可。因此,删除的本质只是允许被覆盖,并不会真正去删除文件的属性和内容这些数据。如果删除文件时,就直接删除数据,更加频繁的 IO 会导致整机效率的降低,并且存储设备的寿命减少。

  • 查找文件
    根据文件所在路径确定分区,再根据文件 inode 编号确定所在分区,查找 inode Bitmap 发现文件有效之后,通过位图索引到 inode Table 中对应的 inode,读取文件属性。如果类似 cat file.txt 读取文件内容,那么就再通过 inode 中的 block 数组找到所有的数据块,把数据块内容做拼接,最后显示打印在显示器上。

  • 修改文件
    不管是 chmod 修改文件权限,还是 touch 修改文件时间,又或者修改文件内容。只要拿到文件 inode 编号,修改属性的话就直接对 inode 中的属性做修改。修改内容,如果原来数据块空间不够用了,那就在 Block Bitmap 中重新找到可用的数据块,分配给该文件inode,最后把新增的数据块映射在 inode 中的 block 数组上不就行了。

2. 文件名 与 inode 的关联

在 linux 系统中,一个文件有一个 inode,每一个inode都有自己的 inode 编号( inode 分配,是以分区为单位的,不能跨分区),inode 中记录了文件的所有属性,但不包括文件名,文件名并不属于 inode 内的属性!

但是,作为操作系统的使用者,我如何得知一个文件的 inode 编号?用户可从来不关心 inode,在对文件进行操作时,用的也都是文件名啊! 那我们平时用的文件名到底和 inode 之间有什么关联呢??

目录也是文件,也有 inode,因此目录也有自己的文件属性!

在这里插入图片描述

而目录不仅有属性,它也是有内容的,所以目录也需要分配数据块。目录文件的数据块存放的就是该目录下所有文件名 与文件对应的 inode 编号之间的映射关系,是一组 kv 结构的数据。

换言之,如果我想要找到目录下的某一个文件时,必须先找到该目录文件的 inode,然后根据该目录文件的 inode,找到其属性和内容,读取它的数据块,就能够知道该目录下的文件和对应文件的 inode 的映射关系,进而找到文件。

  • 所以我们也就自然能够理解为什么同一目录下,不允许存在相同的文件名,因为一切文件操作是根据文件的 inode 编号执行的,而目录的数据块中,是以文件名作为 key 值映射查找文件的 inode,所以文件名当然不一样,不然怎么映射对应文件的 inode,每个文件的 inode 可是具有唯一性的!
  • 如果目录没有 w 权限,是无法创建文件,删除文件等一切对文件做写操作的行为。这是因为,如果目录权限规定了不具备写权限,那么即便文件在该目录已经被创建出来了,该文件的文件名与 inode 编号的映射关系也无法写入目录的数据块中, 没有映射关系,别说写文件了、删文件了,就连该目录下的文件的属性和数据,你都无法找到。
  • 同理,如果目录没有 r 权限,无法查看文件属性和内容。目录不让用户读取数据,用户就无法读取目录的数据块,因此也就无法拿到该目录下的文件和对应文件的 inode 编号的映射关系,也就拿不到文件的 inode,一切文件操作就无法进行。
  • 目录没有 x 权限,我们就无法进入该目录。当 cd 进入目录时,需要拿到目录的 inode 编号,然后把更新系统中的环境变量的信息,但是这中间会多一条判断,如果发现该目录没有 x 权限,则驳回一切请求。

到这里,大家必须要有一个疑问:

找一个文件时,需要先找到该文件所在目录的 inode,进而根据目录文件的 inode 找到其数据块,才能根据文件名知道我这个文件的 inode,这一点没问题,但是我怎么知道该目录的 inode 呢??一个目录一定是另一个目录的子目录,所以按照这种逻辑,我是不是得一路向上递归,想要找这个文件 inode,就得找当前目录的 inode,想要找当前目录的 inode,就得找上级目录的 inode,这不就是套娃吗?!

好在我们的根目录的名字是固定的,因此根目录的 inode 一定能够找到,因为它是不变的。所以只要我递归找到根目录的 inode,我就能够一层一层把 inode 返回,最终找到我这个文件所在目录的 inode,然后找我的文件 inode。这也是为什么我们在进行文件操作时,一定需要有路径,没有路径是找不到当前文件的 inode 的!

你说的不对!我在执行 ls,touch,mkdir 这类指令时,我压根就没带路径!

不!那只是你觉得没带路径,诸如上述这种系统指令,其程序所在目录早就在系统中的环境变量中配置好了,当你执行这些指令时,操作系统会自动带上环境变量中的路径。任何文件执行起来都会带上路径,包括自己写的可执行程序文件,执行起来变为进程,进程也有当前工作目录 cwd.

可是,如果是按照这种思想,我要找一个文件,需要一直递归找到根目录,再把 inode 层层返回才能拿到我想要的文件的 inode,那岂不是太慢了。

没错的,所以操作系统对此采用了一个 dentry 缓存,操作系统会把常访问的若干目录,以及递归查找目录 inode 时经过的各种文件名,文件对应的 inode 属性信息,包括使用过的路径信息全部缓存起来,这样就不需要每次都递归查找文件 inode 了。

3. 软硬链接

ln -s file.txt sotf-link	# 软链接
ln test.txt hard-link		# 硬链接[outlier@localhost inode]$ ls -li
total 0
#			【硬链接数】/【引用计数】
34150680 -rw-rw-r--  1  outlier outlier 0 Aug 13 16:07 file.txt
34165047 -rw-rw-r--  2  outlier outlier 0 Aug 13 16:07 hard-link
34150681 lrwxrwxrwx  1  outlier outlier 8 Aug 13 16:07 sotf-link -> file.txt
34165047 -rw-rw-r--  2  outlier outlier 0 Aug 13 16:07 test.txt

软链接是一个独立的文件,对 file.txt 建立软链接,sotf-link 的 inode 编号与 file.txt 并不相同!因为软链接具有独立的 inode!

相反,硬链接不是一个独立的文件,因为太没有独立的 inode,它的 inode 编号与 test.txt 是相同的。

3.1 理解硬链接

在这里插入图片描述

对 test.txt 做了硬链接,hard-link 与 test.txt 是同一个 inode,所以就注定了它们的文件属性是一模一样的。因为 inode 是同一个,因此在文件系统上,inode Table 里面最终找到的都是同一个 inode,里面的文件属性自然也就一样了,不仅如此,它们所指向的数据块也是一样的。这也就再次印证了,inode 中不保存文件名信息;如果 inode 中保存了文件名,那么就不可能出现同一个 inode 会有两个不同的文件名的现象。

还记得上面讲过,一个文件的文件名与其对应的 inode 编号的映射关系,就存储在所在目录的数据块中!那硬链接做了什么事呢?硬链接的本质就是在特定目录的数据块中新增 文件名 和 硬链接指向的目标文件的 inode 编号的映射关系!

任意一个文件,无论是目录还是普通文件,都有 inode,每一个 inode 内部都有一个引用计数。而目录的数据块保存的是 文件名 与 对应文件的 inode 编号的映射关系,假如有 file1、file2、file3、file4 都与编号为 123456 的 inode 建立了映射关系,换言之,这几个文件名都指向了 inode123456,而引用计数就是记录有多少个文件指向当前 inode!

所以如果这种说法是正确的话,那么当我删除一个文件名时,本质就是 引用计数 -1 的操作,直到引用计数为 0 时,才会清空该文件 inode 所对应的位图结构(Block Bitmap 和 inode Bitmap)

在这里插入图片描述

而我们创建出来的普通文件,其引用计数一定是 1,因为在该目录下,只有你创建出来的这个文件名与该文件的 inode 编号做了映射啊!

3.2 理解软链接

在这里插入图片描述

软链接与目标文件的 inode 编号并不相同,这就说明软链接是一个独立的文件,也就拥有独立的文件属性和数据块,它的数据块保存的就是指向目标文件的路径!

所以只要我对软链接做读取,是可以读取到目标文件的内容的。

在这里插入图片描述

既然软链接是一个独立的文件,所以把软链接删除,不会影响目标文件;反之,软链接文件的数据块存储的是目标文件的路径,因此把目标文件删除了,软链接也就无法使用了。软链接的作用就相当于 windows 平台中的快捷方式!

3.3 软硬链接的应用场景

  • 软链接:
    在发布一个应用程序时,很多都不止是一个可执行程序那么简单,还会有与该应用息息相关的各种配置文件 conf,也有 bin 目录下的各种二进制文件,也包括可执行程序。但一个应用程序发布时,往往都不会把可执行程序直接暴露给用户,而是对其做一个软链接(即快捷方式),供用户使用。

  • 硬链接:

    在这里插入图片描述

    在一个路径下,创建一个新目录 dir,为什么它的硬链接数就是 2 了??

    因为每个目录都会存在两个隐藏文件,一个 . 当前目录,一个 .. 上级路径,. 不就是指向当前这个目录 dir 吗,加上 dir 自己,一共不就有两个文件名指向 dir 目录吗??并且可以看到 . 这个隐藏文件的 inode 编号与 dir 目录的 inode 编号是一样的,换言之,. 就是目录 dir 的硬链接!所以 dir 目录的引用计数 / 硬链接数自然就等于 2 了。

    再看,所以为什么 .. 的硬链接数位 3 呢?? (上级目录名假设为 inode)

    .. 代表上级目录,上一个目录也得有 ... 这两个隐藏文件吧。所以上级目录 inode 自己 + inode 目录内的 . 文件,再加上 dir 目录内的 .. 指向 inode 目录,一共就有三个文件指向 inode 目录!因此 inode 的硬链接数为 3,也即 dir 目录内的 … 硬链接数为 3,它们是指向的都是同一个 inode 和数据块。

    所以,如果我在 dir 目录下再创建一个 subdir,那么 dir 的引用计数将会变为 3,原因与上面同理,dir 自己 + dir 目录内的 . 文 + subdir 目录内的 .. ,一共三个文件指向 dir 目录,因此 dir 的引用计数为 3。

    在这里插入图片描述

    所以我们是能够发现一个规律的,一个目录内部如果没有子目录,那么它的引用计数为 2,多新增一个子目录,那么引用计数就会 + 1,因为新增的目录里面会有一个 .. 文件指向上级目录。因此我们查看一个目录的引用计数,就能够得知该目录下有多少子目录。

    所以硬链接通常用来进行路径定位,采用硬链接,可以进行目录间的切换。但作为用户,linux 不允许用户为一个目录建立硬链接,因为这样会导致文件系统出现环路问题,但目录内的两个隐藏文件的本质也是一个环,只不过那是操作系统的设计者建立的硬链接,操作系统设计者可以通过硬编码完成这件事,但并没有给操作系统的使用者这个权限,root 用户也不具备该权限,所以给目录建立硬链接,我们用户无法完成。

    在这里插入图片描述

    环路问题:当我们给一个目录 dir 建立链接 hard-link 之后,我们 find 查找一个普通文件时,查找的路径上如果碰到了dir的硬链接,那么就会指向 dir,然后就又回到了 dir 目录开始往下找,这就是环路问题。同样的,假如你 find 查找 .. 这类文件时也会导致环路问题,所以操作系统在搜索时不对目录下的两个隐藏文件做搜索。


如果感觉该篇文章给你带来了收获,可以 点赞👍 + 收藏⭐️ + 关注➕ 支持一下!

感谢各位观看!

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

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

相关文章

在线查看 Android 系统源代码 AOSPXRef and AndroidXRef

在线查看 Android 系统源代码 AOSPXRef and AndroidXRef 1. AOSPXRef1.1. http://aospxref.com/android-14.0.0_r2/1.2. build/envsetup.sh 2. AndroidXRef2.1. http://androidxref.com/9.0.0_r3/2.2. build/envsetup.sh 3. HELLO AndroidReferences 1. AOSPXRef http://aospx…

JAVA基础面试题总结(十五)——设计模式

面试专题-设计模式 前言 在平时的开发中,涉及到设计模式的有两块内容,第一个是我们平时使用的框架(比如spring、mybatis等),第二个是我们自己开发业务使用的设计模式。 面试官一般比较关心的是你在开发过程中&#…

浮动元素详解

浮动元素 代码实现&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>浮动元素</title><style>#container1 {width: 400px;height: 50px;background-color: lightgrey;border: 1px solid;}#contai…

828华为云征文|华为云Flexus云服务器X实例之openEuler系统下dufs文件服务器

828华为云征文&#xff5c;华为云Flexus云服务器X实例之openEuler系统下dufs文件服务器 一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、dufs介绍2.1 dufs简介2.2 dufs特点2.3 使用场景 三、本次实践…

学习整理vue前端框架项目目录结构的含义

学习整理vue前端框架项目目录结构的含义 1、目录结构2、结构含义 1、目录结构 2、结构含义

大模型大侦探-一次丝滑的探图记录

文章目录 缘起调查深入确认总结 缘起 最近找到了我的一台老笔记本电脑&#xff0c;竟然还能开机&#xff0c;是XP的。里面有一个桌面&#xff0c;叫做panMilk: 这太美了&#xff0c;但这是哪里&#xff1f;这个问题在20年前就困扰了我&#xff0c;不得答案。这些年学校、公司的…

CorrMatch复现

复现结果–Full&#xff1a;81.78327847863439&#xff0c;成功 U2PL’s splits计算量太大&#xff0c;不建议复现

美团图床设置教程

大厂图床&#xff0c;CDN加速 项目地址&#xff1a;https://github.com/woniu336/mt-img 使用方法 在mt.php填上你的token即可&#xff0c;然后打开index.html上传图片 获取token方法 注册https://czz.meituan.com/发布视频&#xff0c;上传封面&#xff0c;注意在上传封面后…

2024年汉字小达人区级自由报名备考冲刺:往年真题练一练

2024年第十一届汉字小达人的区级活动的时间9月25-30日正式开赛&#xff0c;还有不到两周时间。 最后的冲刺时间&#xff0c;可以利用接下来的三天中秋假期做几套模拟题&#xff0c;熟悉汉字小达人的比赛形式、考察方式&#xff0c;尤其是把2024年的模拟题做做熟&#xff0c;查…

2、HDFS编程实践

目录 1、Hadoop三种Shell方式(1)目录操作1、查看目录2、创建目录3、删除目录 &#xff08;2&#xff09;文件操作1、创建文件2、上传文件3、下载文件4、拷贝文件 2、利用Web界面管理HDFS3、利用Java API 与 HDFS 进行交互&#xff08;1&#xff09;安装eclipse包&#xff08;2&…

CH1-1 引论

一、参考教材 清华大学出版社《数值分析》李庆扬 王能超 易大义 编 数值分析 机械工业出版社 Numerical Analysis David Kincaid Ward Cheney 著 二、课程背景 所学内容在数学学科体系里的位置: 所学内容: 计算数学是广泛的研究框架,数值分析(教材名)是理论研究,计算…

Python基础知识学习(2)

一&#xff0c;分支条件判断语句 在python中&#xff0c;分支条件语句如下&#xff1a; 1&#xff0c;判断条件&#xff1a;if exception: 2&#xff0c;接着判断的语句为&#xff1a;elif exception: 3&#xff0c;最后的条件为&#xff1a;else: 4&#xff0c;通过缩进来表示…

在线查看 Android 系统源代码 Git repositories on android

在线查看 Android 系统源代码 Git repositories on android 1. Git repositories on android1.1. Android Make Build System1.2. Android Open Source Project Code Review References 1. Git repositories on android https://android.googlesource.com/ 1.1. Android Make …

C++笔记之子类初始化时父类带参构造函数的处理、父子类中模板参数的传递

C++笔记之子类初始化时父类带参构造函数的处理、父子类中模板参数的传递 code review! 文章目录 C++笔记之子类初始化时父类带参构造函数的处理、父子类中模板参数的传递一.子类初始化时父类带参构造函数的处理1.1.若父类只有带参数的构造函数,子类初始化时必须在初始化列表…

[Python学习日记-22] Python 中的字符编码(下)

[Python学习日记-22] Python 中的字符编码&#xff08;下&#xff09; 简介 编码的战国时代 Unicode 和 UTF 现代计算机系统通用的字符编码工作方式 简介 在[Python学习日记-21] Python 中的字符编码&#xff08;上&#xff09;中我们讲了字符编码中的 ASCII 码和 GB2312/G…

18060 删除空格

**思路**: 1. 使用两个指针&#xff0c;一个指向当前字符位置&#xff0c;另一个指向下一个非空格字符应该放置的位置。 2. 遍历字符串&#xff0c;如果当前字符不是空格&#xff0c;则将其移动到目标位置指针处&#xff0c;并递增目标位置指针。 3. 最后在目标位置指针处添加字…

新电脑安装和配置pytorch、anaconda、CUDA、cuDNN、pycharm、OpenCV的过程记录

显卡驱动和CUDA 一、升级显卡驱动到官方最新版 1、打开英伟达官网&#xff0c;输入显卡芯片型号&#xff0c;手动搜索并下载显卡驱动。 NVIDIA 官方驱动 ​ 2、下载完成后安装驱动。 二、确认显卡支持的最高CUDA版本 1、键盘"winR"&#xff0c;调出运行输入cmd后…

查询中的算术表达式

需要修改数据显示方式&#xff0c;如执行计算&#xff0c;或者作假定推测&#xff0c;这些都可能用到算术表达式。 一个算术表达式可以包含列名、固定的数字值和算术运算符。 使用算术运算符 示例&#xff1a;查询雇员的年薪&#xff0c;并显示他们的雇员ID&#xff0c;名字…

支付域——聚合支付设计

摘要 聚合支付是支付行业的一项重要创新&#xff0c;通过整合多种支付方式&#xff0c;极大简化了支付流程&#xff0c;提升了交易效率&#xff0c;为商户和消费者提供了更加便捷的支付体验。随着移动支付的普及&#xff0c;聚合支付在未来的支付场景中将继续发挥重要作用&…

bat批量修改文件名

一、bat代码 代码如下&#xff0c;其中csv_file中记录了原来的文件名字和要修改为的新文件名字&#xff0c;folder是img所在的文件路径。 echo off setlocal enabledelayedexpansion set "csv_fileD:\img\1.csv" set "folderD:\img\" for /f "…