Linux | 磁盘结构 | 文件系统认识 | inode | 软硬链接

磁盘物理结构的认识

在这里插入图片描述
在这里插入图片描述
(图片来自于网络)一个磁盘由许多盘片构成,每个盘片上有着许多磁道,每个磁道被分为大小相等的扇区,虽然内外磁道的扇区大小不同,但一个扇区的大小为512字节,不论它的面积是否相等,大小始终为512字节,并且磁盘的基本单位为512字节,但不意味着操作系统访问磁盘的基本单位为512字节,一般情况下,操作系统访问磁盘的基本单位为4k字节。

为什么系统访问磁盘的基本单位是4k字节?1.提高IO效率,如果系统访问磁盘的基本单位和磁盘的基本单位一样,为512字节,那么原本IO一次就能访问的空间大小,现在却需要IO8次才能有相等的效果,要知道磁盘作为外设,找一个特定扇区需要不断的旋转盘片,调整磁头,这个过程是十分耗时的,所以IO次数越多,访问数据的效率越低,将4k作为访问磁盘的基本单位是为了提高IO的效率。

2.将系统与底层硬件解耦。无论磁盘的基本单位怎样变化,操作系统访问磁盘的基本单位始终是4k字节,操作系统的上层接口将4k字节作为数据传输的基本单位,统一了传输的最小数据量,所以这个4k字节就像是一个标准,如果操作系统访问磁盘的基本单位与磁盘的基本单位相同,那么操作系统与底层的硬件就具有了强相关性,当磁盘的基本单位变化,操作系统访问磁盘的基本单位也随之变化,标准IO的基本单位也需要跟着变化,很显然一个频繁变化的标准是不好的。操作系统将4k字节作为访问磁盘的基本单位,无论磁盘的基本单位如何变化,只需要有一层中间层,调整操作系统访问磁盘的基本单位为4k字节即可,这样使得访问磁盘的标准固定,无论底层硬件的标准怎样改变,操作系统的IO标准都不需要变化,这样,操作系统与底层硬件就实现了解耦。

磁盘的分区

扇区是磁盘的最小单位,盘片由一块块扇区构成,磁盘由多个盘片构成,磁盘最终的物理结构是圆形的,但我们可以将磁盘抽象成一个很大的数组,在磁盘中读写数据,等价于对数组存取数据。

我们将扇区在磁盘上的地址称为CHS,C表示磁道地址,H表示盘片地址,S表示扇区地址。将磁盘抽象成数组后,扇区的地址被称为LBA(逻辑块地址),操作系统得到LBA地址,将LBA转换成CHS,然后在磁盘上寻找扇区存储数据。
在这里插入图片描述
一个数组可以分为多个区,这里以4个区为例,每个区又被分成多个块组,块组用来存储数据。在Linux系统中,文件分为内容和属性,文件系统将内容和属性分开存储

块组是文件系统中最小的单位,结合上图,块组的结构为:

Data Blocks:数据块,存储文件内容,以4k字节为基本单位存储数据
inode Table:inode表,存储文件属性,以128字节为基本单位存储数据
Block Bitmap:块位图,以位图结构表示Data Blocks中数据块的使用情况
inode Bitmap:inode位图,以位图结构表示inode Table中inode块的使用情况
GDT(Group Descriptor Table):块组的总大小是多少?块组中有多少数据块,inode块有多少被使用?还剩多少?总的来说GDT存储了这一个块组的所有信息
Super Block:该块组所处的分区的大小,分区中有几个块组,分区还能存储多少数据,每个块组的inode,数据块有多少,每个块组的使用情况。总的来说Super Block存储了一个分区的信息

Super Block存储的是分区的信息,却不保存在分区,而是保存在分区下的块组中的原因:如果Super Block保存在分区下,那么一个分区只有一个Super Block,如果程序异常导致Super Block出现数据丢失,那么一整个分区的信息都会丢失。也不是每个块组中都保存了Super Block,只有部分的块组保存了Super Block,当其中一个Super Block出现数据丢失,可以将其他块组的Super Block的数据拷贝到丢失数据的Super Block上,因为它们保存的数据都是相同的,这样的多个备份无疑增加了文件系统的稳定性。

至于GDT中存储的数据可以通过遍历Block Bitmap和inode Bitmap得到,为什么要有GDT这个结构?原因是遍历两个位图所消耗的时间大于遍历GDT所需要的时间,并且由于inode具有全局的属性,GDT中保存了一个块组中inode的起始编号,通过偏移量可以知道块组中的inode号的范围,综上GDT对于块组是必要的。

inode和文件数据之间的映射

Linux将文件的属性和内容分开存储,Data Blocks存储文件数据,inode Table存储文件属性。因为文件的属性大小相对固定,所以inode Table的基本单位inode块的大小为128字节,其存储一个文件的属性,每个基本单位都存储了一个文件的属性。而Data Blocks的基本单位block的大小为4k字节,一个文件的内容可能会使用不止一个block,因为文件的内容不固定,而一个文件的属性只会使用一个inode块。在inode块中还有一个blocks数组,数组长度为15,[0,11]元素为存储该文件内容的block编号,这样做,文件的inode Table和Data Blocks之间就建立了映射。但是[0,11]映射的block总共只能存储48kB,由于文件内容可能需要不止48kB空间存储,所以inode块中的blocks数组的[12,14]元素虽然也保存一个block的编号,但该block不存储文件内容,其存储的是block指针,该指针指向的block存储的才是文件的内容,所以blocks数组的[12, 14]元素映射到Data Blocks中的一些block块上,这些block块又映射到其他block块上,blocks数组的12元素作为一个二级索引,扩大了文件内容的存储空间,保证了文件内容的存储空间足够,blocks数组的13元素作为三级索引、14元素则作为四级索引,保证能存储TB级别的文件

总之,知道了文件的inode号,就可以在inode Table中找到对应的inode块,inode块中有一个blocks数组,该数组的元素指向了数据块block,通过索引就能找到存储文件内容的block块。

文件名和inode之间的映射

Linux下,文件属性包括文件名吗?答案是不包括,Linux文件系统不用文件名来标识文件,而是用文件的inode号识别文件。既然文件名不属于文件属性,那么inode块中就不需要存储文件名,那么文件名存储在哪?

要讨论这个问题,需要先了解Linux中一个特殊的文件:目录。Linux下的目录是一个文件吗?在一个目录下创建一个目录文件和一个普通文件,用ll -i可以打印出该目录下的文件信息,以及文件的inode号,通过打印结果,我们发现目录也是有inode号的。所以Linux下,目录是一个文件在这里插入图片描述
之前聊文件权限时说到,进入一个目录需要该目录文件具有x权限,在一个目录下添加文件,需要w权限,查看目录下的文件内容需要r权限。对于进入目录需要的x权限,这是一个规定,没有什么好探究的,但对于目录文件的r和w权限就需要我们深究一下了。

之前说Linux将文件的内容和属性分开存储,一个目录文件的属性很好理解,就是关于该目录的创建时间,修改时间,创建人等等。但是一个目录文件的内容该存储什么呢?根据之前的铺垫:Linux不用文件名标识文件,但我们创建的文件却都有文件名,这些文件名被存储在了哪里?其实所谓的文件名被存储到了目录文件的内容中,具体地说,一个目录文件的内容存储了文件名和对应inode的映射关系

当一个文件没有被打开时,它存储在磁盘中,打开一个文件时,操作系统只知道文件的文件名,因为Linux不用文件名标识文件,所以系统无法在磁盘中根据文件名找到对应文件。系统需要查找该文件的所在目录,并在目录文件的内容中(目录文件的内容存储的是文件名和inode之间的映射关系)根据文件名查找对应的inode号,根据inode号,找到块组中的inode Table,在Table中找到该inode对应的inode块,根据inode块中blocks数组的映射找到文件的内容,最终将他们加载到内存中。

上面说的是一个文件被打开的过程,通过我们对文件系统的理解,一个文件被创建的过程也能被很好的理解:系统在磁盘的扇区上找到块组,遍历块组中的inode Bitmap,找到一个为0的元素并将其置1表示该块被使用,根据该元素的下标算出inode编号,接着在inode Table中找到对应的inode块,如果文件要进行写入,就需要与block建立映射关系,并修改inode块中的blocks数组,将映射关系写入,最后在对应block块中写入数据。该过程中,最重要的是要在文件所处的目录文件的内容中添加映射关系,将该文件名和对应的inode号添加到目录文件的内容中。需要注意的是,Linux下不允许相同文件名的文件出现,因为文件名是一个类似key值的对象,需要具有唯一性才能准确的查找inode。

(用户不能直接看到目录文件的内容,操作系统将其隐藏了,也许是出于安全考虑,我们只需理解文件系统的原理即可)

删除一个文件的过程:这个“删除”其实不是真正意义上的删除,操作系统通过文件名找到对应的inode块,再通过inode块中的blocks数组找到该文件所使用的数据块编号,系统只需要将文件所使用的数据块位图和inode位图中的1置为0就可以了,最后只要删除该文件所处目录文件的内容中的该文件名与inode的映射关系,一个文件的删除操作就完成了。所以在生活中,下载一部电影需要的时间往往很长,但删除一部电影的时间却非常快,其中的原因正是因为系统没有真正删除数据,只是改变位图中的数据,以及删除目录内容中的映射关系。如果文件系统没有被频繁写入,即之前的文件数据虽然被删除了,但数据却在磁盘中,仍然可以通过特殊手段将其恢复(这里有点像局部变量的生命周期问题,可以结合函数的栈帧理解)。

所以回到最开始的问题,目录文件有w权限表示可以在该目录下创建文件,本质是因为创建文件需要修改所处目录文件的内容以添加映射关系,r权限表示可以读取所处目录下的所有文件信息,本质就是读取该目录文件的内容,将文件名和inode这对映射关系中的文件名打印。

文件知道自己的inode号吗?

读取一个文件的信息需要找到存储文件内容的数据块,系统通过文件名在文件所处目录的内容文件下查找映射该文件名的inode号,但是系统要怎么访问该文件所处目录的内容文件,换言之就是要怎么读取当前文件所处目录的数据,由于系统只知道目录名,不知道目录名的inode,所以需要到上级目录查找其inode,系统需要访问上级目录的内容文件,但不知道上级目录的inode,所以需要通过它的上级目录知道上级目录的inode…不断重复这个过程,系统会访问到根目录,根目录不属于任何目录,所以操作系统不能向上访问,最终到根目录停止,可以猜测,系统肯定可以直接或间接地读取根目录的内容文件,从而得知根目录下所有文件的inode,接着重复访问到根目录过程的逆过程,最终得到所需要访问文件的inode号访问文件。

文件的软硬链接

文件有两种链接方式,软链接和硬链接,链接文件是一种创建文件的方式,所以链接文件创建出的文件名不能重复,下面是链接文件的指令

ln -s 原文件名 软链接文件名
ln 原文件名 硬链接文件名

通过代码说明软硬链接的区别
在这里插入图片描述
现在我处于11_13这个目录,里面有一个test.exe程序,该程序简单的打印一句话
在这里插入图片描述
进入mydir目录,在该目录下以软链接的方式创建一个文件test.soft.ext,使文件与11_13目录下的test.exe文件进行软链接,执行链接文件
在这里插入图片描述
该链接文件打印出与原文件相同的内容,再以硬链接的方式链接11_13目录下的test.exe文件,执行链接文件,打印的内容也和原文件相同。所以执行链接文件的效果与执行源文件的效果相同,那么软硬链接的区别在哪呢?
在这里插入图片描述
在这里插入图片描述
注意原文件test.exe的inode号1183655,和硬链接的文件inode相同,和软连接的文件inode不同。通过这个现象,可以得知:硬链接产生的文件与软链接的文件虽然文件名不同,但不同文件名映射的inode号却是相同的,也就是说有两个文件名映射到了同一个inode文件上,所以硬链接不创建独立的文件,需要依赖一个已经存在的文件,硬链接只是创建了一个映射方式。

而软链接就像Linux中的快捷方式,软链接创建了一个新的系统级文件,该文件名映射的inode文件与原文件不同,其内容存储了原文件的绝对路径(绝对路径指向的文件也可以不存在),所以文件较小,运行软链接文件,实际上是运行其内容中存储的绝对路径指向的文件,也就是原文件。所以从原理的角度上说,如果分别以软链接和硬链接的方式链接同一个程序,执行硬链接程序的速度和执行原程序的是一样的,执行软链接程序会相对慢一些,因为软链接相当于一个索引,系统需要打开两次文件。

综上,软硬链接的区别就是:硬链接没创建系统级别的文件,只是在所处目录下添加了一个映射关系,而软连接创建了系统级别的文件,保存了原文件的绝对路径。

硬链接数

在这里插入图片描述
用ll指令打印文件的具体信息,在文件权限信息后面的数字就是文件的硬链接数,在一个目录下创建一个目录文件和一个普通文件,为什么目录文件的硬链接是2,普通文件的硬链接数是1?

普通文件的硬链接数是1:硬链接数像一个计数器,记录当前有几个文件名指向了该inode文件,很显然,普通文件只有自己的文件名指向了其inode文件,所以它的硬链接数为1。至于目录文件的硬链接数为什么是2,因为除了目录自己的名字指向了inode文件,还有一个该目录下的隐藏文件.指向了inode文件
在这里插入图片描述
进入mydir目录,ll -ai打印该目录下的隐藏文件的具体信息,发现一个空目录有两个隐藏文件.和…,.表示当前目录mydir,…表示上级目录11_13,它们是对应目录的其他名字
在这里插入图片描述
可以看到.文件对应的inode和mydir的inode相同,说明两个文件指向了同一个inode文件,虽然名字不同,但底层的文件却是相同的。所以在11_13目录下创建一个空目录mydir后,除了mydir的目录名指向了其inode,还有mydir目录下的文件.也指向了其inode,所以mydir的硬链接数为2。因此一个空目录的硬链接数为2
在这里插入图片描述
再进入上级目录,ll -i打印目录下的文件信息,可以看到11_13这个文件的inode为1183649,和mydir目录下的…所映射的inode相同,…表示mydir的上级目录11_13,两者的inode相同。经验证.映射当前目录文件,…映射上级目录文件,两者为一个目录下的隐藏文件。

总结:硬链接数表示指向同一文件的inode的文件名数量。删除文件时,系统会将文件的硬链接数-1,如果硬链接数被减到0,系统才会将文件真正的删除

为什么目录不支持硬链接?

一个硬链接文件与原文件的内容和属性完全相同,即它们的拥有者,所属组相关权限,甚至是创建时间都一样,原因很简单,因为在底层结构上,硬链接文件与原文件指向了同一个inode,它们唯一的区别就是用来指向inode文件的文件名不同。而文件名甚至不属于Linux文件的属性,所以文件名是无关紧要的。假如你在当前目录下创建了一个硬链接文件,该文件链接了当前目录,使用du(遍历所有文件以计算磁盘的大小)指令时,系统遇到这个硬链接文件,发现其是一个目录就会进入目录,遍历目录下的文件,但该硬链接文件却指向了当前目录,这就导致了一个环路,破坏了文件系统结构,使之出现了死循环,这将导致系统的崩溃,系统中有关查找文件的指令都会崩溃,所以Linux禁止对目录创建硬链接。

但是,我在当前目录下创建一个软链接,使之链接当前目录,执行du指令时,文件系统是否会出现环路呢?答案是不会,因为软链接后的文件其实是一种符号文件,系统通过lstat能够识别文件的类型,当识别到该文件为一个符号文件,就不会对其进行遍历,因为系统知道如果遍历可能导致死循环的出现,所以系统可以通过文件类型检测文件是否是符号文件,避免环路的出现。

所以,可以说硬链接产生的文件和普通文件没有任何区别,软链接产生的文件为符号文件,是一种特殊的文件。关于软硬链接的区别,也有人说其区别就是是否能被系统检测到

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值