025 理解文件系统

理解文件系统

1. 认识磁盘磁带

由于磁盘磁带和操作系统组成原理更相关,而且相关概念用语言太抽象,所以我找到了一些比较好的视频和书籍内容来帮助理解(注意视频、书籍内容有部分知识我们不涉及,所以不懂也没关系,多出的就当是眼界扩展了):

硬盘驱动器是如何工作的?(You Tube)

硬盘的工作原理(B 站)

机械硬盘是如何工作的?(B 站)

机械磁盘:结构与工作原理详解

磁带为何能记录声音?(主要了解其存储原理)

相关文章 | 博客园

相关文章 | CSDN

相关文章 | CSDN

摘自《操作系统概念精要 原书第 2 版》298 页前后(真的是很想将内容直接摘过来,奈何实在是没找到电子版,只能扫描现书将就看吧 😂)。这里的图片已经排好序,直接按照顺序看即可。推荐直接去看原书,也希望有电子版的进行贡献一下,感谢您的开源精神!

image-20250506203138105

8d8a9a29b2373d90ba4e09a41ccf2bcb

image-20250506203402279

image-20250506203527455

image-20250506203703623

image-20250506203757884

image-20250506203840852

image-20250506204215459

自然也少不了鸟哥啦~ 摘自《鸟哥的 Linux 私房菜 基础学习篇(第四版)》210~`217` 页相关内容。还是推荐看原书,就不过多赘述了。

首先说明一下磁盘的物理组成,整颗磁盘的组成主要有:

  • 圆形的盘片(主要记录数据的部分);
  • 机械手臂,与在机械手臂上的磁头(可读写盘片上的数据);
  • 主轴马达,可以转动盘片,让机械手臂的磁头在盘片上读写数据。

从上面我们知道数据储存与读取的重点在于盘片,而盘片上的物理组成则为(假设此磁盘为单碟片,盘片图示请参考第二章图 2.2.1 的示意):

image-20250506205841870

  • 扇区 (Sector)为最小的物理储存单位,且依据磁盘设计的不同,目前主要有 512Bytes 与 4K 两种格式;
  • 将扇区组成一个圆,那就是柱面 (Cylinder) ;
  • 早期的分区主要以柱面为最小分区单位,现在的分区通常使用扇区为最小分区单位(每个扇区都有其号码喔,就好像座位一样);
  • 磁盘分区表主要有两种格式,一种是限制较多的 MBR 分区表,一种是较新且限制较少的 GPT 分区表。
  • MBR 分区表中,第一个扇区最重要,里面有:主引导记录(Master boot record,MBR)及分区表 (partition table) , 其中 MBR 占有 446B, 而分区表则占有 64B
  • GPT 分区表除了分区数量扩充较多之外,支持的磁盘容量也可以超过 2TB

至于磁盘的文件名部份,基本上,所有物理磁盘的文件名都已经被仿真成 /dev/sd[a-p] 的格式,第一块磁盘文件名为 /dev/sda。而分区的文件名若以第一块磁盘为例,则为 /dev/sda[1-128]。除了物理磁盘之外,虚拟机的磁盘通常为 /dev/vd[a-p] 的格式。

复习完物理组成后,来复习一下磁盘分区吧!如前所述,以前磁盘分区最小单位经常是柱面,但 CentOS7 的分区软件,已经将最小单位改成扇区了,所以容量大小的分区可以切的更细 〜 此外,由于新的大容量磁盘大多得要使用 GPT 分区表才能够使用全部的容量,因此过去那个 MBR 的传统磁盘分区表限制就不会存在了。不过,由于还是有小磁盘啊!因此,你在处理分区的时候,还是得要先查询一下,你的分区是 MBR 的分区?还是 GPT 的分区?在第三章的 CentOS7 安装中,鸟哥建议过强制使用 GPT 分区喔!

文件系统特性

传统的磁盘与文件系统之应用中,一个分区就是只能够被格式化成为一个文件系统,所以我们可以说一个文件系统就是一个硬盘分区。但是由于新技术的利用,例如我们常听到的 LVM 与软件磁盘阵列 (softwareraid),这些技术可以将一个分区格式化为多个文件系统(例如 LVM),也能够将多个分区合成一个文件系统 (LVM,RAID)。所以说,目前我们在格式化时已经不再说成针对硬盘分区来格式化了,通常我们可以称呼 一个可被挂载的数据为一个文件系统而不是一个分区喔!

那么文件系统是如何运行的呢?这与操作系统的文件数据有关。较新的操作系统的文件数据除了文件实际内容外,通常含有非常多的属性,例如 Linux 操作系统的文件权限 (rwx)与文件属性(拥有者丶用户组丶时间参数等)。文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,至于实际数据则放置到数据区块中。 另外,还有一个超级区块 (super 数据区块) 会记录整个文件系统的整体信息,包括 inode 与数据区块的总量、使用量、剩余量等。

每个 inode 与区块都有编号,至于这三个数据的意义可以简略说明如下:

  • 超级区块 ∶ 记录此 f 文件系统的整体信息,包括 inode 与数据区块的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
  • inode:记录文件的属性,一个文件占用一个 inode,同时记录此文件的数据所在的区块号码;
  • 数据区块:实际记录文件的内容,若文件太大时,会占用多个区块。

由于每个 inode 与数据区块都有编号,而每个文件都会占用一个 inode inode 内则有文件数据放置的数据区块号码。因此,我们可以知道的是,如果能够找到文件的 inode 的话,那么自然就会知道这个文件所放置数据的数据区块号码,当然也就能够读出该文件的实际数据了。这是个比较有效率的作法,因为如此一来我们的磁盘就能够在短时间内读取出全部的数据,读写的性能比较好啰。

我们将 inode 与数据区块区块用图解来说明一下,如下图所示,文件系统先格式化出 inode 与数据区块的区块,假设某一个文件的属性与权限数据是放置到 inode 4 号(下图较小方格内),而这个 inode 记录了文件数据的实际放置点为 2,7,13,15 这四个数据区块号码,此时我们的操作系统就能够据此来排列磁盘的读取顺序,可以一口气将四个数据区块内容读出来!那么数据的读取就如同下图中的箭头所指定的模样了。

image-20250506212505957

这种数据存取的方法我们称为索引式文件系统 (indexed allocation)。那有没有其他的惯用文件系统可以比较一下啊?有的,那就是我们惯用的 U 盘(闪存),U 盘使用的文件系统一般为 FAT 格式。FAT 这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有区块在一开始就读取出来。每个区块号码都记录在前一个区块当中,他的读取方式有点像下面这样:

image-20250506212829181

上图中我们假设文件的数据依序写入 1->7->4->15 号这四个 block 号码中,但这个文件系统没有办法一口气就知道四个区块的号码,他得要一个一个的将区块读出后,才会知道下一个区块在何处。如果同一个文件数据写入的区块分散的太过厉害时,则我们的磁头将无法在磁盘转一圈就读到所有的数据,因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!

常常会听到所谓的碎片整理吧?需要碎片整理的原因就是文件写入的区块太过于离散了,此时文件读取的性能将会变的很差所致。 这个时候 可以通过碎片整理将同一个文件所属的区块集合在一起,这样数据的读取会比较容易啊! 因此,FAT 的文件系统需要时不时的碎片整理一下,那么 Ext2 是否需要磁盘重整呢?

由于 Ext2 是索引式文件系统,基本上不太需要常常进行碎片整理的。但是如果文件系统使用太久,常常删除、编辑、新增文件时,那么还是可能会造成文件数据太过于离散的问题,此时或许会需要进行重整一下的。不过,老实说,鸟哥倒是没有在 Linux 操作系统上面进行过 Ext2/Ext3 文件系统的碎片整理,似乎不太需要啦!


太多了,还是看图片吧 😂

image-20250506214005755

image-20250506214113160

image-20250506214325696


2. 磁带、HDD、SSD 数据存储原理与演进

磁带是最古老的电子数据存储技术之一,其介质为带有磁性涂层的长条塑料薄膜。数据以磁化痕迹形式记录在磁带上:写入时磁头通过控制磁场使带面上的磁性颗粒朝向发生改变,分别表示二进制的 0 或 1;读取时固定的磁头感应这些磁化痕迹输出数据。磁带基片通常是聚酯薄膜,上面涂覆氧化铁或金属磁粉层。磁带读取为串行访问,速度较慢但容量极大,而且成本低廉、耐用性高,因此常用于海量数据的长期归档和备份。

小知识

  1. 固态硬盘(SSD):不属于磁盘或硬盘(HDD),因其使用闪存芯片而非磁性介质。
  2. 关系总结
    • 磁盘 是技术大类(磁性存储),硬盘 是磁盘的现代主流应用。
    • 日常中“磁盘”有时被误用作“硬盘”的同义词,但严格意义上前者更广泛。
对比项 硬盘(HDD, Hard Disk Drive) 磁盘(广义) 关系说明
定义 一种使用磁性存储技术的物理存储设备,属于磁盘的一种具体类型。 广义指所有利用磁性记录数据的圆形盘片(如软盘、硬盘中的盘片)。 硬盘是磁盘的一种具体应用形式,磁盘的概念更广泛。
存储原理 通过磁头在高速旋转的磁性盘片上读写数据。 依赖磁性材料记录数据(如硬盘盘片、软盘等)。 硬盘的存储基于磁盘的磁性原理。
常见类型 机械硬盘(HDD 包括硬盘中的盘片、软盘(Floppy Disk)、早期磁光盘(MO)等。 硬盘是磁盘技术的主流应用之一,其他磁盘类型逐渐被淘汰或小众化。
速度 较慢(依赖机械转动,通常转速 5400/7200 RPM)。 取决于类型(如软盘速度远低于硬盘)。 硬盘速度优于大多数传统磁盘介质。
容量 大(当前主流 1TB~20TB)。 差异大(软盘仅 1.44MB,硬盘盘片单碟可达数 TB)。 硬盘是磁盘技术中容量发展的巅峰代表。
体积/便携性 体积较大(3.5 英寸或 2.5 英寸)。 灵活(软盘小巧,硬盘盘片不可单独使用)。 磁盘的形态多样,硬盘更注重固定存储。
应用场景 电脑、服务器等大容量存储需求。 历史曾用于数据交换(软盘)、临时存储等,现硬盘主要用于长期存储。 硬盘取代了多数传统磁盘的用途。
价格 较低(单位容量成本低)。 历史中软盘成本低,但现代高性能磁盘(如企业级硬盘)价格较高。 硬盘性价比高,是磁盘技术的经济化产物。
发展趋势 逐渐被 SSD 替代,但仍在大容量存储中占优。 传统磁盘技术(如软盘)已淘汰,硬盘技术仍在优化。 SSD(固态硬盘)不属于磁盘范畴,但硬盘仍是磁性存储的重要选择。

3. 硬盘 (HDD) 存储原理

硬盘通过磁性方式在旋转的盘片上存储二进制数据。 每个盘片表面涂覆磁性材料,盘片由主马达高速旋转,而机械臂上的磁头在盘片上方移动进行读写。盘片表面被划分为同心圆形的磁道(track)和扇区(sector),每个扇区通常固定容量(如 512B4096B);这些磁道和扇区号构成了数据的物理地址。盘片上的微小磁颗粒可以被磁化成两种极性,分别代表二进制 01。写入时,磁头在线圈通电后在盘片下方产生磁场,将被选区域的小颗粒磁极方向改变以记录信息;读取时,磁头感知磁性材料的极性排列并将其转换为电信号恢复出数据。HDD 提供随机访问能力,因而读写延迟主要受磁头寻道和盘片旋转时间影响。

4. 固态硬盘 (SSD) 存储原理

SSD 使用闪存芯片(典型的 NAND Flash)作为存储介质,无机械活动部件。每个闪存单元是一个带浮栅的 MOSFET 晶体管,通过存储电荷来保存数据。当浮栅中注入电子时,晶体管阈值变化被解读为二进制“0”;当浮栅不带电子时则被视为二进制“1”。SSD 写入数据时,控制器通常需要先擦除整个块(块内所有单元恢复为空状态),然后才将新数据写入(利用高压使电子通过隧道注入浮栅)。由于没有机械部件,SSD 读写速度远快于 HDD。另一方面,闪存擦写次数有限,SSD 控制器必须使用磨损平衡(wear leveling)和 TRIM 等技术均衡使用单元并回收空间。总的来说,SSD 速度高、无噪音、功耗低,但成本相对较高且写入寿命有限。

image-20250506231740872

5. HDD 未被淘汰的原因

虽然 SSD 性能优秀,但 HDD 凭借成本和容量优势仍不可替代。根据权威资料,对于大容量、冷备份或归档场景,经济实惠的 HDD 依然是首选。AWS 指出“若需要高速频繁访问用 SSD;处理备份、归档或大容量存储时,普通硬盘是更好的选择”。此外,HDD 技术发展成熟,数据恢复难度更低,长期保存历史数据也更稳定可靠。有些公司可能会将用户长期不访问的数据/很多年前的数据从 SSD 迁移至磁盘,从而长期保存数据并节约成本。


上面我们已经基本上了解了磁盘磁带的构造和存储、读写的原理,下面就到我的讲解了:

6. 文件系统磁盘布局(重点)

image-20250507122425391

image-20250507122324436

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+----------------------+  <- 偏移 0
| Boot Block | (第 0 块, 1KB/2KB/4KB)
+----------------------+ <- 偏移 BLOCK_SIZE
| Superblock (SB) | (备份 SB 存放在每个 Block Group 的第 0/1/2 块)
+----------------------+ <- 偏移 BLOCK_SIZE + sizeof(SB)
| Group Descriptor Tbl | (每个 Block Group 保持一份)
+----------------------|
| Block Bitmap | (标记该 Group 中哪些数据块已用)
+----------------------|
| Inode Bitmap | (标记该 Group 中哪些 inode 已用)
+----------------------|
| Inode Table | (存放 inode 结构,文件元数据)
+----------------------|
| Data Blocks | (真正存放文件和目录内容的数据区)
| |
| |
+----------------------+
…(重复多个 Block Group)…

注意:

  • Boot Block:文件系统第 0 块(通常 1KB2KB),包含启动加载代码,不属于文件系统使用范围,仅在可启动分区时有意义。
  • Block Group:整个分区被划分成若干个相同大小的 Block Group,以提高并行性并减少碎片。每个 Group 包含上述结构一次。

1. Boot Block(启动块/引导块)

  • 大小1 个块(BLOCK_SIZE),通常 512B4KB
  • 作用:存放引导代码(Bootloader)及分区信息,在 BIOS/UEFI 加载文件系统之前被使用,文件系统本身不访问此区域。
  • 存放位置:分区的第 0 块。

2. Superblock (SB,超级块)

  • 作用:文件系统的“总控信息”,记录整个分区的全局属性。
  • 存放位置:分区的第 1 块(紧跟 Boot Block 之后)。
  • 大小:固定 1024 B
  • 关键字段
    • Magic Number(魔数):文件系统类型标识(如 0xEF53 表示 Ext2/3/4)。
    • Block Size(块大小):数据块大小(常见 4KB)。
    • Total Blocks(总块数):总数据块数。
    • Total Inodes(总 inode 数):总 inode 数。
    • First Inode(第一个 inode:第一个可分配 inode(通常 inode 2 为根目录)。
  • 冗余存储:备份 Superblock 分布在各 Block Group 的第 0/1/2 块,防止损坏。

3. Group Descriptor Table (GDT,块组描述符表)

  • 作用:描述每个 Block Group 的布局信息(如位图、inode 表的位置)。
  • 存放位置:紧跟主 Superblock 之后,占用若干个块。
  • 描述符大小:32 B/个。GroupDescriptorTable 的总大小 = 描述符数 × 32,向上对齐到 BLOCK_SIZE
  • 关键字段
    • block_bitmap(块号): 指向当前 GroupBlock Bitmap 的块号。
    • inode_bitmap(块号): 指向当前 Groupinode Bitmap 的块号。
    • inode_table(起始块号): 指向当前 Groupinode Table 的起始块号。
    • 空闲块数、空闲 inode 数等统计信息。

4. Block Bitmap(块位图)

  • 作用:位图方式标记本组中各数据块是否已分配。
  • 存放位置:由 GDT 中的 block_bitmap 字段指定。
  • 大小:1 个 BLOCK_SIZE(例如 4KB = 32768 bits,能管理 32768 个块 ≈128MB)。
  • 标记规则:1 = 已分配,0 = 空闲。

5. Inode Bitmap(inode 位图)

  • 作用:位图方式标记本组中各 inode 是否已分配。
  • 存放位置:由 GDT 中的 inode_bitmap 字段指定。
  • 大小:1 个 BLOCK_SIZE(例如 4KB 可管理 32768inode)。
  • 标记规则:1 = 已分配,0 = 空闲。

6. Inode Table(inode 表)

  • 作用:存储所有文件/目录的元信息,每个 inode 大小通常为 128B256B
  • 存放位置:由 GDT 中的 inode_table 字段指定,长度 = (inodes_per_group * inode_size) / BLOCK_SIZE 块。
  • 关键字段
    • File Type:普通文件、目录、符号链接等。
    • Permissions:访问权限(rwx)。
    • File Size:文件大小。
    • Timestamps:创建/修改/访问 时间戳。
    • Data Block Pointers:直接指针(12 个)、一级/二级/三级间接指针。

7. Data Blocks(数据块)

  • 作用:实际存放用户数据。所以,Linux 的文件在磁盘中存储是将属性和内容分开存储的!(文件内容 → 数据块,文件属性 → inode
    • 目录(directory):保存 <inode号, 文件名> 的列表。
    • 普通文件(file):存放文件内容的二进制数据。
  • 存放位置:紧跟在各组的 Inode Table 之后,直至本组末尾。
Block Group 字段 作用 大小/位置
SuperBlock 记录文件系统的全局信息(如总块数、inode 数、块大小等)。 每个 Group 可能有一份副本(冗余)。
Group Descriptor Table 描述当前 Block Group 的元数据(如块位图、inode 位图的位置)。 紧接 SuperBlock 之后。
Block Bitmap 标记当前 Group 中哪些数据块已被占用(1 = 占用,0 = 空闲)。 占用 1 个块,按位映射。
inode Bitmap 标记当前 Group 中哪些 inode 已被占用(类似 Block Bitmap)。 占用 1 个块,按位映射。
inode Table 存储 inode 数组,每个 inode 描述一个文件/目录的元数据(权限、大小、数据块指针等)。 占用多个块,具体取决于 inode 数量。
Data Blocks 实际存储文件数据的块。 剩余所有块。

8. 对比记忆

记忆 作用 类比
SuperBlock 文件系统的“总说明书”。 书的目录页。
Group Descriptor Table 描述每个 Block Group 的布局。 章节的页码索引。
Block Bitmap 标记哪些块被占用。 仓库货架占用表。
inode Table 存储文件元信息(如权限、大小)。 文件的属性卡。
Data Blocks 实际存储文件内容。 仓库里的货物。

7. 深入理解(重点)

1. 创建空文件的过程

  1. 查找空闲 inode:遍历 inode 位图,找到一个空闲 inode
  2. 初始化 inode:在 inode 表中找到对应 inode,填入文件的属性信息(如创建时间、权限、大小等)。
  3. 关联目录项:在当前目录文件的数据块中,增加一条目录项(文件名 + inode 号)。

2. 写入文件的过程

  1. 根据文件名找到对应 inode(通过目录的数据块中查找 inode 号)。
  2. 读取 inode 内容,查看已分配的数据块。
  3. 如果存在空余数据块,直接写入。
  4. 若数据块已满:
    • 遍历块位图找到空闲数据块,分配并标记为已用。
    • inode 中的数据块指针数组中记录该数据块号。
    • 写入数据。

inode 与数据块的映射关系:

使用一个 15 元素的数组维护:

  • 12 个元素:直接指向 12 个数据块
  • 3 个元素:一级索引、二级索引和三级索引(用于数据块扩展)

3. 删除文件的过程

  1. 标记 inode 无效:在 inode 位图中将对应 inode 置为无效。
  2. 标记数据块无效:在块位图中将文件使用的数据块置为无效。
  3. 删除映射关系: 删除对应目录文件中该文件的目录项(文件名和 inode 号的映射关系)。

注意:删除操作只是标记为无效(标记为“可复用”)而非真正擦除数据,因此短时间内可恢复。后续文件操作可能重新分配这些 inode 和数据块,导致原数据被覆盖。这也就是数据恢复的原理:删除 = 允许被覆盖。

为什么是“短时间”?

  • 被标记为空闲的 inode 号和数据块号可能在新文件或写入时重新分配。
  • 一旦覆盖,原始数据就不可恢复。

4. 拷贝 vs 删除 的时间差异

  • 拷贝文件慢
    • 创建新 inode
    • 分配多个数据块。
    • 写入文件内容(复制)。
  • 删除文件快
    • 只需修改 inode 和块位图。
    • 不需要物理/真实的删除文件内容。

类比:

  • 创建文件 = 建楼 → 慢
  • 删除文件 = 在楼上写“拆”字 → 快

5. 目录的理解

  • 在 Linux 中“一切皆文件”,目录也属于文件。
  • 目录有自己的 inode(属性信息)和数据块(内容)。
  • 目录的数据块内容:该目录下的文件名 与 对应 inode 号的映射表。

目录权限

  • w 权限:无法创建文件。
  • r 权限:无法查看文件列表。
  • x 权限:无法进入目录。

特别说明:

  • 文件名不存储在 inode 中,而是存储在它所在目录文件的数据块中。
  • 系统通过“目录项”建立文件名和 inode 号的联系。

6. 文件系统中增删查改系统要做什么?

操作 系统执行的步骤概要
新建文件 分配 inode、数据块,更新目录项
删除文件 inode/块标记无效,删除目录项
查找文件 遍历目录数据块,找 inode,再查 inode 内容
修改文件 定位 inode,追加/覆盖数据块

7. 查看文件的 inode 编号

1
ls -i 文件名
  • 使用者通过文件名访问文件。
  • 内核通过目录项映射找到 inode。