【Linux系统】Ext系列磁盘文件系统二:引入文件系统
引入文件系统
1、引入"块"概念
其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样效率太低,而是⼀次性连续读取多个扇区,即⼀次性读取一个”块”(block)。
硬盘的每个分区是被划分为一个个的”块”。一个”块”的大小是由格式化的时候确定的,并且不可以更改,最常⻅的是4KB(4096字节),即连续八个扇区组成一个”块”(扇区为 512B,8*512=4096)。”块”是文件存取的最小单位,而每个数据块的编号就是 块号
#### LBA 地址和块号的相互转换
在物理层面,磁盘就是一个三维数组,而在逻辑上,磁盘则是以块为单位的一维数组,数组下标就是 LBA,每个元素都是一个扇区。每个扇区都有 LBA,那么 8 个扇区一个块,每一个块的地址我们也能算出来。
- 知道LBA:块号 = LBA / 8
- 知道块号:LAB = 号 * 8 + n (n 是块内第几个扇区)
操作系统和磁盘的交互,就是以块为单位交互,想要使用哪一个块,就提供块号,通过快号翻译成8个扇区号,通过 CHS寻址法找到在磁盘中的物理地址。
结构图示
1、CHS 地址 可以简单理解成 三维地址,LBA 地址 可以简单理解成 一维地址
2、CHS 地址和 LBA 地址可以相互转换
3、LBA 地址转换成快号:即 除于 8
我的Windows系统上的数据块
其实我们电脑上存储的:文档、代码、图片、视频、代码,都是一个个 4KB 的块,也就是按照一个数据块为单位大小存储,你在电脑上查看某些文件(文档、代码、图片…都行),只要该文件数据是小于 4kb 的,则大概率显示该文件占用空间为 4kb (文件有两种属性:文件实际大小与占用空间)
假设你有一个文件,其实际大小为 2KB:
- 文件实际大小:2KB
- 文件占用空间:由于文件系统使用 4KB 的数据块,即使文件只有 2KB,它也会占用一个完整的 4KB 数据块。
- 显示的占用空间:在文件属性中,你会看到文件占用的空间为 4KB。
2、引入"分区"概念
操作系统如何管理磁盘
磁盘有百GB级别的,有TB级别的,操作系统不可能一下子管理整个磁盘空间
而我们国家 960万平方公里,不可能直接对全部土地直接管理,而是通过将土地划分成省、市、区 ,只要区长管理好一个区,市长管理好区长,省长管理好市长,这样通过区域划分的方式管理,就能达到管理整个大区域的目的
而操作系统管理磁盘也一样:通过给磁盘划分区域
而我们电脑上会有 C盘、D盘…. 其实本质电脑上只有一块盘, C盘、D盘是对电脑的磁盘做分区
我们只需要管理好一块分区,然后再将这样的管理方式复用到其他分区,就实现了一种方式管理多个分区,以致于管理整个盘的目的。
而一块分区也可以分成多个小组,然后管理好一个小组,将该管理方式复用到其他组,进而复用到其他分区,以致于管理整个盘。
这样的管理方式的思想即为:分治!
其实磁盘是可以被分成多个分区(partition)的,以 Windows 观点来看,你可能会有⼀块磁盘并且将 它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的⼀种格式化。但是Linux的设备 都是以文件形式存在,那是怎么分区的呢?
命令 ls /dev/vda*
:查看当前你的系统盘有多少分区,下图中第一个没有序号的是物理盘,其他的就是该盘的分区
另外说一下
分区的隔离性和独立性:分区除了能够将大块空间分开管理,每个分区之间还是“相互独立“ 的!不同的分区可以配置不同的文件系统(甚至一台PC的不同分区可以安装不同的操作系统)。另外,若某个分区挂掉了,也不会对其他分区造成较大影响。
分区概念图
一个分区会分成多个块组,即如图所示图中所示的 Block group
,一个块组 Block group
中包含着许多其他概念,如 Supert Block、Block Bitmap、inode Bitmap、inode table.....
,这些概念在后续文章中都会一一解释。
本知识讲解是先细致到讲解一个块组(Block group
) ,最后到上升到整个分区,以致于整个磁盘空间。
我们先从 “inode” 讲起:
3、inode
引入 “inode” 概念
命令 ls -l
:查看当前目录下文件的属性信息
其实这个信息除了通过这种方式来读取,还有一个 stat 命令能够看到更多信息,例如:
到这我们要思考一个问题,文件 = 文件内容 + 文件属性,文件内容数据储存在“块”中,那么很显然,我们还必须找到一个地方储存文件的元信息(即文件属性信息),比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做 inode
,中文译名为“索引节点”。
每一个文件都有对应的 inode
,里面包含了与该文件有关的⼀些信息。为了能解释清楚 inode
,我们需要是深入了解一下文件系统。
inode
的概念
- 文件 = 内容 + 属性
- 属性也是数据,属性使用结构体的方式构建出来,即为
inode
inode
是文件属性数据的集合,包含大部分文件的属性信息,如文件权限、文件属主….- 一个文件一个对应一个
inode
,一个inode
一般是 128 字节(有的系统会是 256字节)
inode
存储文件的属性,并作为文件的一部分存储在磁盘中,命令 ls -l
即为读取存储在磁盘上的文件信息,然后显示出来,之前我们讲过一个打开的文件在内存中会描述成一个文件结构体 struct file
,该结构体中存储着文件的属性信息,这些信息也是从 inode
中读取并拷贝的!!!
因此,文件属性的本质上就是存储在 inode
中!
inode
号
一个文件一个对应一个 inode
,每个文件的 inode
都有一个 inode
编号,一般是唯一的,就和进程的唯一 pid
一样:
命令:ls -l -i
可以看到各个文件的 inode
值
一个文件就对应一个 inode
,而一个分区中有多个文件,多个文件的 inode
就需要通过某些数据结构管理起来,即分区块组 Block group
中的 inode table
:
4、inode table
inode table
用于存储磁盘分区中的所有文件的 inode
。
如果要存储 10000 个文件的 inode
,该inode table
需要多大空间:10000*128 / (4*1024)
约等于 312个 4KB 大小的数据块(一个 inode
为 128字节大小)
inode table
像是一个 inode
结构类型的数组
inode Block
存储 文件属性集 inode
,而文件内容则存储在 Data Block
中:
5、Data Blocks
整个区域为数据块区,其中包含一个个 4KB 的数据块,用于存放文件内容,而该区域占该磁盘分组中的绝大部分空间区域
若你在系统磁盘中存储一个文件,磁盘会将该文件的属性全部填写到一个 struct inode
结构中,然后在磁盘中某分区某分组的 inode table
中记录该文件的 inode
,另外该文件的内容则存储于 Data Blocks
中。
因此,在 Linux
下,文件属性和文件内容,是分开存储的!!
学习到这里,我们基本可以认识到,磁盘会进行分区管理,每个分区中有多个块组 Block group
,而一个文件的内容存储在该块组中的 Data Blocks
,文件的属性存储在该块组中的 inode table
,我们该如何寻找一个磁盘中文件?
如何找到一个磁盘中文件:
基本过程:文件的 inode
号是存储在上层的(即内存层),用户可以通过该 inode
号在磁盘的 inode table
中索引找到对应文件的 struct inode
,在该 struct inode
中,会存在一个 int block[num]
的数组结构,系统可以通过 int block[num]
找到 Data Blocks
中该文件的数据块,即文件内容。(至于 int block[num]
具体是什么,后面会详细说 )
简单来说:若想要在一个磁盘中寻找某一文件,用户只需要通过 inode
,找到分区中该文件的 struct inode
,就可以进一步获取该文件的属性和内容,也就是达到寻找该文件的目的
抛出一个问题:
现在我们已经了解了文件系统中的 inode table
(索引节点表)和 Data Blocks
(数据块集合)。这些区域分别用于存储文件的元数据和实际内容。具体来说,inode table
中包含一个个的 inode
结构,每个 inode
保存了一个文件的属性信息;而Data Blocks
则用于存储文件的实际数据。
那么,系统是如何知道inode table
中有多少个inode
以及有多少空间被占用了呢?同样地,系统又是如何追踪Data Blocks
内部的数据块使用情况的呢?
如果当前存入一个文件,系统是如何为该文件分配文件属性和文件内容的存储位置?
那就需要查找 inode table
(索引节点表)和 Data Blocks
(数据块集合) 中是否有空位置,直接遍历查询,效率太低,我们可以使用位图机制,即为 inode bitmap
和 Block bitmap
!!
6、inode bitmap
该结构运用了位图(bitmap
)的思想
inode bitmap
是文件系统中用于管理 inode
分配状态的一种数据结构。它通过位图(bitmap)的方式记录哪些 inode
已经被分配,哪些 inode
仍然可用。每个位(bit)代表一个 inode
,1 表示已分配,0 表示未分配。
- 分配
inode
:- 当创建新文件时,文件系统会查找
inode bitmap
中的第一个为 0 的位,表示该inode
可用。 - 将该位设置为 1,表示该
inode
已经被分配。
- 当创建新文件时,文件系统会查找
- 回收
inode
:- 当删除文件时,文件系统会将该文件的
inode
对应的位设置为 0,表示该inode
可用。
- 当删除文件时,文件系统会将该文件的
例如下图:
inode table
中,红色格子代表这个位置已被占用,而白格则表示该位置空闲
inode bitmap
中,就对应着 inode table
,若位置被占用,则 inode bitmap
对应位置置为 1,否则为 0。
而 inode bitmap
通常会使用整型类型的数据按位存储:
假设有一个文件系统,它有1024个inode。为了追踪这些inode的使用情况,使用了一个inode bitmap。
要表示这 1024 个 inode 是否被使用,只需要 1024 位比特(用整型数据表示,即128字节,因为每字节包含8位)。
磁盘中不是以扇区或数据块为单位存储吗,但通常inode bitmap很小甚至只有1KB或2KB,那磁盘如何存储如此小的数据。
比如一万个文件的 inode bitmap
也就是 一万个比特位,即 10000/8/1024 = 1.多KB
- 尽管
inode bitmap
可能只有 1KB 或 2KB,但它仍然会被存储在一个 4KB 的数据块中。 - 文件系统会分配一个完整的数据块来存储这些小数据结构,即使它们没有填满整个块。
7、block bitmap
block bitmap
道理和 inode bitmap
相同,都是以位图形式,用比特位来标识和记录每个数据块的使用情况
当需要为文件分配存储空间时,系统会查询 block bitmap
以查找空闲的数据块。
系统找到第一个比特位标记为 0 的位置,这表示找到了一个未使用的数据块。
然后将这个比特位置为 1,标记该数据块现在已被占用,并将该数据块分配给请求的文件。
释放数据块:当文件被删除或某些数据块不再需要时,这些数据块会被标记回未使用状态(即将对应的比特位从 1 改回 0 ),从而允许它们再次被分配给其他文件使用。
学到这里,我们认识了文件系统通过两张位图来记录 两块区域空间的 资源使用情况,下面我们通过一个一个新文件的存储例子,梳理一下这些知识的运用思路:
8、文件如何被创建并存储到磁盘
当系统需要创建一个新文件时,会执行以下步骤来完成从文件创建到数据存储的全过程:
-
查询
inode bitmap
:首先,系统会在inode bitmap
中查找是否有标记为0(未使用的)的位置。找到后,将该位置置为1,表示这个inode
位置已被占用。 -
申请
inode
:根据在inode bitmap
中找到的位置,在inode table
中对应的位置上分配一个新的inode
。然后,系统将关于新文件的相关属性信息(如文件创建者、创建时间、文件权限等)填写到这个inode
中。 -
计算所需存储空间:接着,系统根据要存储的文件内容(例如"hello world")计算所需的存储大小,并确定需要多少个数据块来存放这些数据。
-
查询
block bitmap
并分配数据块:系统随后在block bitmap
中查找空闲的数据块位置(比特位为0)。找到足够的空闲数据块后,将对应的比特位设置为1,表明这些数据块已被占用。 -
存储文件数据:在
Data Blocks
中,系统将文件数据写入之前选定的数据块中。 -
更新
inode
中的数据块信息:最后,系统通过文件的inode
号定位到inode table
中对应的inode
,并将刚刚使用的所有数据块的块号记录到该inode
的int blocks[num]
数组中。这样就完成了文件数据与它的inode
之间的关联。
通过上述步骤,系统成功地完成了一次文件从创建到数据存储的完整过程!!
9、文件如何被删除
这个比较好理解,因为文件的 inode
号是该文件存在的凭证,我们可以通过 inode
号 找到该文件的 struct inode
,根据其中记录的文件 inode
和 内容数据块 的位图索引位置,直接在 inode bitmap
和 block bitmap
对应的位置由 1 置 0 。
这样就表示删除该文件,本质是使其占有 inode
和 block
无效,把这些空间的使用状态置为空闲!
其实原来的内容没有被真正删除,当空间的使用状态置为空闲后,这些内容也就在形式上被删除了!
如果误删一个文件,最好的方式是什么也别做,如果该文件的 inode
被重新被占用,则你再也不可能恢复原文件了
最好的做法是立即停止对文件系统的写操作,以尽量减少数据被覆盖的风险
10、文件如何被恢复
既然删除是通过重置对应的 inode bitmap
和 block bitmap
,那么反过来也就可以恢复该文件,只要该文件的数据没有被覆盖。我们就可以通过该被删除文件的 inode
号,将 inode bitmap
恢复为 1,然后通过 inode
中的 int blocks[num]
中的 block
数据块号,找到 block bitmap
恢复为 1,将空间的使用状态重新置为 1,这样就完成一个文件的恢复
11、Super Block
#### 超级块表示文件系统
超级块(Super Block):存放文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:block 和 inode 的总量,未使用的 block 和 inode 的数量,一个 block 和 inode 的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间、整个分区的大小、每个块组的大小以及文件系统的总块组数量(可以推导出各块组的起始与结束地址)等其他文件系统的相关信息。
需要注意的是,超级块并不直接存储每一个块组的具体位置信息.
可以说,超级块就表示文件系统,Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
超级块也可以理解成一个复杂机器的使用说明书,它将有关于该系统的操作信息都交代清楚
因为超级块就表示文件系统,分区之间是独立的,文件不同分区可以写不同的文件系统!
每个分区都可以划分为不同的组块,每个组块的超级块中就记录了给文件分区使用的文件系统,例子如下:
- 分区 1 使用
ext2
文件系统,则分区 1 中的组块超级块就记录了当前分区使用的是ext2
文件系统 - 分区 2 使用
ext3
文件系统,则分区 2 中的组块超级块就记录了当前分区使用的是ext3
文件系统
分区中超级块的数量
其实不是分区中每个组都有一个超级块
全部都有 还是 只需一个:
一个分区通常会指定使用某种文件系统,但其实没必要在该分区中给每个组块,都加上超级块记录整个分区使用的文件系统类型。
理论上,只需在分区的起始位置存储一次超级块来标识整个分区使用的文件系统类型就足够了。
然而,为了提高数据的安全性和系统的稳定性,实际设计中会在分区内的多个组块(block group)中也存储超级块的副本。
其实,如果一个超级块挂掉了,则某种程度上表示该分区的文件系统也就挂掉了,这整个分区的数据会被影响而销毁。
只需几个用于备份:
因此,为了防范这种情况,一个分区可能会有好几个超级块。
Linux
系统设计在分区中的某几个组块中存储一份超级块,这样整个分区就有了好几份超级块的备份数据,当某个超级块挂掉了,还可以查看其它超级块来恢复文件系统
你可能遇到过这样的情况:
打开Windows系统时,收到提示说某文件系统已损坏,并询问是否要进行修复。这种情况通常是由于相关分区的超级块出现问题所致。修复过程实质上是尝试利用超级块的备份来恢复文件系统的一致性。
源码展示
这是官方 ext2
文件系统的源码,可以看到在 超级块 的描述性结构体中,就记录着这些文件系统相关的信息(这里仅仅展示一小部分)
12、GDT(Group Descriptor Table)
- 块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储一个块组的描述信息,如在这个块组中从哪里开始是inode Table,从哪里开始是Data Blocks,空闲的inode和数据块还有多少个等等。
- 块组描述符在每个块组的开头都有一份拷贝。
简单来说:GPT
就是用于描述一个快组的属性信息的,而超级块 super Block
是用于描述整个分区的属性信息的,用途类似,作用范围不同。
源码展示
实际上,一个块组的 GDT
含有本块组的 inode bitmap
和 blocks bitmap
的指针、inode table
和 Data Blocks
的起始位置等等
起到了一个管理块组的作用!
【中场小结】
至此,我们所展示的块组中的大部分属性都讲解了一遍:
Super Block
:描述该分区的文件系统属性信息GDT
:描述该块组的属性信息,管理该块组内的inode bitmap
和blocks bitmap
、inode table
和Data Blocks
等等inode Bitmap
:一种位图,记录本块组inode Table
中inode
资源的分配使用情况Block Bitmap
:一种位图,记录本块组Data Blocks
中 数据块 资源的分配使用情况inode table
:内部存储本块组中可用可分配的inode
资源Data blocks
:内部存储本块组中可用可分配的 数据块 资源
13、格式化
格式化,就是批量删除文件,本质上就是将某分区所有分组的 inode bitmap
和 block bitmap
清零,然后向超级块中写入:本分区的 inode
和 block
数量,新的文件系统….属性
格式化的步骤
- 清零
inode bitmap
和block bitmap
:- 将所有
inode bitmap
和block bitmap
中的位清零,表示所有inode
和数据块都是空闲的,可以被重新分配。
- 将所有
- 初始化超级块:
- 在超级块中写入新的文件系统属性,包括但不限于:
- 文件系统的类型(如 ext4、NTFS 等)
- 分区的总大小
inode
和block
数量- 块大小
- 块组大小
- 时间戳(如创建时间)
- 其他文件系统特定的参数
- 在超级块中写入新的文件系统属性,包括但不限于:
- 初始化
inode table
:- 创建并初始化
inode table
,通常会预分配一些特殊的inode
,例如根目录的inode
。
- 创建并初始化
- 初始化根目录:
- 创建根目录(通常
inode
号为2),并设置其权限和属性。
- 创建根目录(通常
- 创建必要的系统文件和目录:
- 根据文件系统的不同,可能会创建一些系统文件和目录,例如
lost+found
目录(在 ext2/ext3/ext4 文件系统中)。
- 根据文件系统的不同,可能会创建一些系统文件和目录,例如
- 更新
block bitmap
和inode bitmap
:- 将已经分配的
inode
和数据块在inode bitmap
和block bitmap
中标记为已使用。(前面不是 预分配一些的inode
和 创建系统文件和目录文件吗,此时就标记起来 )
- 将已经分配的
14、分区中的 inode
和 block
的数量与分配策略
(1)一个分区中的 inode
和 block
的数量是固定的
一个分区中的 inode
和 block
的数量是固定的,有两个问题:
1、 inode
用完而 block
没有用完
2、 block
用完而 inode
没有用完
1.
inode
用完而block
没有用完完全可能的。
原因:
- 文件数量限制:每个文件系统在创建时都会分配一定数量的
inode
,一个文件对应一个inode
,这些inode
数量决定了该分区最多可以创建多少个文件。- 小文件占用:如果创建了大量的小文件(例如每个文件只有 1KB),这些文件会迅速占用完所有的
inode
,而实际使用的block
数量却很少。示例: 假设一个分区有 100,000 个
inode
和 1,000,000 个block
。如果创建了 100,000 个 1KB 的文件,每个文件占用一个inode
和一个block
,那么inode
会被全部用完,而block
只使用了 100,000 个,剩余 900,000 个block
未被使用。
2.block
用完而inode
没有用完这也是完全可能的。
原因:
- 大文件占用:如果创建了一些非常大的文件,这些文件会占用大量的
block
,而inode
的数量相对较少。- 文件数量较少:即使
inode
数量较多,但如果文件数量较少且每个文件都非常大,也可能导致block
先被用完。示例: 假设一个分区有 100,000 个
inode
和 1,000,000 个block
。如果创建了 10 个 100MB 的文件,每个文件占用一个inode
和 100,000 个block
,那么block
会被全部用完,而inode
只使用了 10 个,剩余 99,990 个inode
未被使用。
问题:那如果 inode 和 block 其中一方用完另一方没用完岂不是浪费吗
确实会造成浪费
因此,我们可以通过一些方法来优化这部分资源的使用:
- 在创建文件系统时,可以调整
inode
的数量。 - 优化文件存储策略
- 选择适合的文件系统
(2)inode
的分配策略
一个分区,一套 inode
,分区的这套 inode
是统一编号的
1、一个分区,一套 inode
:inode
是以分区为单位分配的,而不是以整个磁盘为单位分配的,也不是以某个分组为单位分配的。
2、inode
在分配的时候,只需要确定起始 inode
即可:
例如某分区的各个组:
第一个组块 start_inode = 1
第二个组块 start_inode = 1000
表示 第一个组块的 inode
分配编号区间为 [1, 1000]
表示 第二个组块的 inode
分配编号区间为 [1001, 2000]
(3)Block
块号的分配策略
块号也是分区统一编号的,和 inode
的分配策略同理,通过某些计算,可以计算出整个组块需要多少数据块
对于每个块组,只需记录该块组分配块号的起始就可以 :start_block = 1
(4)组内 inode
号 和 块号的分配
核心:新分配的全局编号 = 起始编号 + 其在块组中的相对位置 - 1
假设分区有两个块组:
- 第一个块组的
inode
号起始编号为 1。 - 第二个块组的
inode
号起始编号为 2000。
分配给第二个组的 inode
号
假设现在我们需要在第二个块组中为一个新建文件分配一个 inode
号,过程如下:
-
检查 Inode Bitmap:首先,在第二个块组中查找
inode bitmap
来找到未被使用的inode
。假设找到了第一个未被使用的inode
,其在该块组内的相对位置是第5个(即这是块组中第五个可用的inode
)。 -
计算全局
inode
号:因为第二个块组的inode
起始号是2000,所以新分配的inode
的全局编号将是起始编号加上其在块组中的相对位置减1(因为我们从0开始计数)。因此,如果新文件对应的inode
是块组中的第5个,则其全局inode
号就是2000 + (5 - 1)
= 2004。
这意味着,对于第二个块组而言,分配给新建文件的 inode
号将会是2004(假设这是首次分配并且前4个 inode
已经被占用或此次分配的是第5个 inode
)。
编号在分区内具有唯一性:综上所述,一个分区中的 inode
和 block
的数量是固定的,分配给各个组块的 inode
和 block
的数量也就是固定的,我们可以将分区中的 inode
号 和 block
号 理解成一种全局编号,这些编号在分区内具有唯一性!!!
15、Block group
块组是整个是固定的
Block group
块组含有这些结构,它们的大小都是固定,解释如下:
(1)inode table
和 Data Block
是固定大小
分区中每组都会被分配一个 起始数据块号 和 起始 inode
号 ,通过和下一组的起始数据块号 和 起始 inode
号 ,就能计算出 本组可分配的 inode
号 和 数据块号 的区间
也就表示该组内可以使用的 inode
和 数据块都是固定的!
(2)inode bitmap
和 block bitmap
是固定大小
每个组都确定可使用的 inode
和 数据块 的数量,也就能直接计算出 inode bitmap
和 block bitmap
的大小,既然 inode
和 数据块 的数量固定,则 inode bitmap
和 block bitmap
的大小也固定!
(3) super Block
和 GDT
是固定大小
这是两个固定大小的数据结构,前面文章讲解过,是两个记录属性信息的结构体,其大小固定
因此,这两个区域 super Block
和 GDT
也是固定的!
综上所述,既然 Block group
块组这些结构大小都是固定,则 整个Block group
块组大小也是固定的!!
16、inode号 和 block块号的全局唯一性
inode
号和 Block
块号是在一个分区内,被分配给各个分组的,每个分组能够得到不同区间的 inode号 和 block块号
这就是 inode号 和 block块号的全局分配,具有分区内的全局性,在一个分区的全局范围内,inode号 和 block块号是固定唯一的,这种全局性允许我们跨组别使用其他组的有关资源:
比如:但我们一个组需要使用的 block
数据块不够了,我们可以跨越到其他组中,使用其他组的数据块资源,只需要在对应文件的 struct inode
中的 int blocks[num]
中记录下我们所使用的数据块的块号,尽管可能属于不同组的块资源,但是只要有块号记录,就能找到,这就是块号设置全局性的作用
这就是 Linux
允许创建大文件的原因!!!
17、确定给定 inode
号 和 block
块号在磁盘中的位置(计算)
以 确定给定 inode
在磁盘中的位置 为例
-
遍历块组:首先,需要遍历文件系统的所有块组来找到包含给定
inode
号的那个块组。每个块组都有一个起始inode
号(start_inode
)和一个inode
数量。 -
查找对应的块组:通过比较给定
inode
号与每个块组的start_inode
和其inode
数量,可以确定该inode
属于哪个块组。具体来说,如果给定的inode
号在某个块组的start_inode
和start_inode + inode数量 - 1
范围内,那么这个块组就是我们要找的。 -
计算相对位置:一旦找到了正确的块组,就可以通过公式
(inode号 - start_inode)
来计算出该inode
在其所属块组内的相对位置。这将直接对应到该块组的inode bitmap
中的位置,进而可以定位到具体的inode
数据结构在磁盘上的位置。
block
块号的查找也同理
具体例子
- 文件系统有两个块组。
- 每个块组有1000个
inode
和2000个数据块。 - 第一个块组的起始
inode
号为1,起始块号为1。 - 第二个块组的起始
inode
号为1001(因为第一个块组有1000个inode
),起始块号为2001。
也就是说,第一个块组可分配 inode
号的区间为 [1, 1000]
,第二个块组可分配 inode
号的区间为 [1001, 2000]
。
确定 inode
在磁盘中的位置:假设我们需要找到 inode
号为1050的位置。
-
确定所属块组(确定区间):根据给定
inode
号 1050,我们知道它超过了第一个块组的最大inode
号(1000)。因此,这个inode
属于第二个块组(起始inode
号为1001)。 -
计算相对位置:使用公式
(inode号 - start_inode)
来计算其在块组内的相对位置。对于inode
1050,它的相对位置是1050 - 1001 = 49
。这意味着它是第二个块组中的第50个inode
(因为从0开始计数)。 -
定位到磁盘上的具体位置:知道了
inode
在块组内的相对位置后,就可以通过inode bitmap
找到该inode
的具体位置,并访问其对应的inode
数据结构。
18、OS如何管理磁盘文件系统呢?
前面我们讲解了,如何通过一个给定的 inode
号和 block
号,通过遍历磁盘文件系统的对应分区中的各个分组的,得出 inode
号和 block
号的所属组,还有对文件的新增/删除…
这些操作总不能在磁盘中进行吧:因为磁盘的IO交互效率低,通常都是将相关数据加载到内存中,再进行操作!
进一步来说, OS如何管理这样的磁盘文件系统,让我们能够快速的获取想要的信息呢?
答:在内存中,对磁盘文件系统相关信息,先描述,再组织!
系统会在内存中创建,磁盘中不同分区的 struct super_block
和 不同组块的 struct gdt
,将这些结构体作为链表节点,用链表链接起来,将对文件系统的管理,转换为对链表数据结构的增删查改!
磁盘的信息也在内存中使用某种数据结构描述起来,最终可以转换成一种文件,这样我们又认识到了 Linux
下一切皆文件的含义!
19、给定 inode
号回答四个问题
下面这些问题的回答都有点粗略,还有某些属性没讲,后面会补充更加详细的讲解
1、如何查找一个文件
通过 inode
号,通过区间确定的方式确定在该分区的哪个组块中,通过该组块的 GDT
中存储的 start_inode
,通过相减的方式,就能确定该 inode
在位图 inode bitmap
中的位置,通过位图位置,找到 inode table
中的对应位置的 inode
结构体,这样成功获取 inode
属性
通过 inode
结构体中的 inode
与数据块block
的映射关系:数据块块号合集 int blocks[num]
找到数据块的位置,就能获取该文件位置
2、如何删除一个文件
先查找该文件,然后将对应的 inode bitmap
和 block bitmap
直接置为零
最后还要更新该组块的 GDT
属性,例如:该组块中的未被使用的inode
数量++……
3、如何新增一个文件
核心思路:查询分区中,某组块是否有空闲位置,然后将 bitmap
中的某空闲位置置为 1,然后在 inode table
中给他创建一个新的 struct inode
、然后对数据块做同样的操作用于分配所需数据块空间,最后还要更新组块的相关属性
4、如何修改一个文件
若修改该文件的相关属性(文件的所属组、创建时间…),直接将该文件的 struct inode
加载到内核缓冲区中
若修改该文件的内容,则将内容加载到内核缓冲区中,
最后修改后统一写回文件原位置
原文地址:https://blog.csdn.net/2301_79499548/article/details/145162393
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!