第19讲 文件系统I

第19讲 文件系统I
agsd从数据块到文件:文件系统如何组织持久化存储
引言
从用户的视角看,存储设备中存在的是文件和目录:文件有名字、大小、类型和权限,目录可以容纳其他文件,应用程序能够按照路径打开、读取、修改或删除它们。
然而,在硬盘或SSD的底层,并不存在天然的“文件”概念。存储设备提供给操作系统的,本质上只是一大片可以按照编号访问的存储块。它不知道某些块属于一张图片,另一些块属于一段视频,更不知道/home/aster/demo.txt这样的路径意味着什么。
因此,文件系统需要完成一次关键的抽象转换:
1 | 底层:一系列编号的数据块 |
文件系统的核心任务,就是记录文件由哪些数据块组成,为文件建立名称与层级关系,管理空闲空间,并在设备故障或异常断电后尽可能维持结构的一致性。
围绕“如何定位一个文件的数据”,不同文件系统发展出了不同方案。inode文件系统采用多级索引,FAT使用簇链表,NTFS则围绕MFT、区段和树形索引建立更加统一的元数据体系。它们的具体结构不同,但解决的本质问题相同:如何在有限的元数据开销下,高效地组织数量庞大、大小不一且不断变化的文件。
一、块设备:文件系统面对的物理基础
硬盘和SSD通常被操作系统抽象为块设备。所谓块设备,是指操作系统不会直接要求设备读取某个孤立字节,而是以一整块数据作为基本读写单位。
典型请求可能是:
1 | 读取第1000号块 |
而不是:
1 | 读取设备上的第83021个字节 |
机械硬盘需要移动磁头、等待盘片旋转并读取一段连续区域。读取一个字节与读取一小块连续数据相比,机械定位成本几乎没有区别,因此逐字节访问缺乏效率。
SSD虽然不存在磁头和盘片,但闪存也按照页、擦除块等较大单位组织数据。它不能像普通内存一样随意覆盖单个字节,因此同样适合以块设备的形式向操作系统提供接口。
1. 不同层次的“块”
“块”并不是一个只属于某一层的概念。存储系统中存在多种大小可能相同、含义却完全不同的单位。
| 概念 | 所属层次 | 主要作用 |
|---|---|---|
| 硬盘扇区 | 存储硬件 | 硬盘实际读写和寻址单位 |
| 闪存页或擦除块 | SSD内部 | 闪存编程、读取和擦除单位 |
| 文件系统块 | 文件系统 | 分配文件空间和记录数据位置 |
| 簇 | FAT、NTFS等文件系统 | 由一个或多个扇区组成的空间分配单位 |
| 内存页 | 虚拟内存系统 | 地址映射、换页和内存保护 |
文件系统块与内存页都可能是4KB,但不能因此将二者视为同一对象。前者描述持久化存储空间,后者描述内存管理空间。文件被读取时,磁盘块中的内容可能进入页缓存并占用内存页,但这是两个层次之间的数据转移,而不是概念上的等同。
❗ 本节核心结论: 文件系统不是直接管理“文件”,而是建立在块设备之上,将底层编号块重新解释成文件与目录。
二、从应用程序到存储设备:文件访问的软件路径
应用程序不会直接操作硬盘扇区。一次文件读取通常需要经过多个软件层次:
flowchart TD
A[应用程序] --> B[VFS虚拟文件系统]
B --> C[具体文件系统]
C --> D[页缓存]
C --> E[块层与I/O调度]
E --> F[设备驱动]
F --> G[硬盘或SSD]
这条路径中的各层承担不同职责:
- VFS虚拟文件系统提供统一的文件操作接口,使应用程序不必关心底层使用的是ext4、FAT还是其他文件系统。
- 具体文件系统理解磁盘上的实际数据结构,例如inode、目录项、FAT表或MFT。
- 页缓存在内存中保留最近访问的文件内容,减少重复磁盘I/O。
- 块层将不同存储设备统一抽象为可编号、可读写的块。
- I/O调度器合并和排序请求,降低随机访问成本。
- 设备驱动把通用块请求转换为具体硬件能够执行的命令。
这种分层结构体现了操作系统中常见的抽象原则:上层负责表达“想读取哪个文件”,下层逐渐把这一请求翻译成“读取设备上的哪些块”。
❗ 文件系统的作用并不只是保存数据。 它还位于文件名、路径、逻辑偏移和物理块之间,承担完整的解释与映射工作。
三、文件的逻辑形式与物理形式
对于应用程序而言,文件通常表现为一段从偏移量0开始的连续字节序列。文本、图片、视频、源代码和PDF在文件系统眼中并没有本质区别。
文件系统只负责保存字节:
1 | .png字节序列 → 由图片软件解释 |
文件系统不需要理解图片中的像素、程序中的语句或视频中的帧。数据的语义属于应用层,文件系统只维护字节的持久化、位置和元数据。
1. 逻辑连续不等于物理连续
假设一个文件大小为4GB,文件系统块大小为4KB,那么它需要约:
1 | 4GB ÷ 4KB = 1,048,576个数据块 |
如果要求这100多万个块必须连续存放,会出现严重问题:
- 设备中未必存在足够大的连续空闲区域。
- 文件增长时,紧邻其后的空间可能已被其他文件占用。
- 文件创建和删除会不断制造外部碎片。
- 为扩展文件而整体搬迁数据的成本过高。
因此,现代文件系统通常允许一个文件的数据块分散在设备的不同位置。文件在逻辑上仍然是一段连续字节序列,但其物理块可以不连续。
于是,文件系统必须回答一个关键问题:
给定文件中的某个逻辑偏移,应该到设备上的哪个数据块读取内容?
inode、FAT和MFT正是这个问题的不同答案。
❗ 本节核心结论: 文件对应用程序表现为连续字节序列,但其数据可以分散在不同物理块中;文件系统必须保存逻辑位置到物理位置的映射。
四、inode:用多级索引定位文件数据
在许多类Unix文件系统中,文件由inode描述。inode可以理解为文件在文件系统内部的档案记录。
一个inode通常保存两类信息:
文件元数据:
- 文件类型
- 文件大小
- 访问权限
- 所有者UID和GID
- 时间信息
- 硬链接数量
数据定位信息:
- 直接数据块指针
- 一级间接指针
- 二级或更高级间接指针
需要特别注意的是,inode通常不保存文件名。文件名保存在目录项中,由目录项把名字映射到inode编号。
完整关系是:
1 | 文件名 → inode编号 → inode → 文件数据块 |
1. 为什么不能保存一个巨大指针数组
假设一个大文件包含100万个数据块,每个块地址占8B,那么仅记录所有块地址就需要:
1 | 1,000,000 × 8B = 8MB |
如果每个inode都预留如此巨大的指针数组,那么即使文件只有几百字节,也要承担大量无用的索引空间。
问题的矛盾在于:
- 小文件只需要极少的数据块,索引应当尽量简单。
- 大文件可能包含数百万个块,索引又必须具有扩展能力。
inode通过多级索引解决了这一矛盾。
2. 直接指针与间接指针
一种典型的教学模型包含:
- 12个直接指针
- 3个一级间接指针
- 1个二级间接指针
flowchart LR
I[inode] --> D[直接指针]
D --> DB[数据块]
I --> S[一级间接指针]
S --> IB[一级索引块]
IB --> DB2[数据块]
I --> T[二级间接指针]
T --> L2[二级索引块]
L2 --> L1[一级索引块]
L1 --> DB3[数据块]
直接指针直接保存数据块地址,访问时不需要读取额外索引块,因此特别适合小文件。
假设块大小为4KB,12个直接指针可以表示:
1 | 12 × 4KB = 48KB |
一级间接指针指向一个专门保存块地址的索引块。若索引块大小为4KB,每个地址占8B,则一个索引块可以保存:
1 | 4KB ÷ 8B = 512个指针 |
一个一级间接指针能够表示:
1 | 512 × 4KB = 2MB |
三个一级间接指针可以表示约6MB文件数据。
二级间接指针先指向一个二级索引块,其中的每个指针再指向一个一级索引块,因此可以表示:
1 | 512 × 512 × 4KB = 1GB |
在这一示例中,最大文件大小约为:
1 | 48KB + 6MB + 1GB |
真实文件系统可能使用三级间接指针,也可能采用extent等更现代的区段机制,但其设计思想相同:小文件使用简单路径,大文件按需增加索引层次。
3. 多级索引的“按需付费”
inode不会为所有文件提前建立完整索引树。
- 小文件只使用直接指针。
- 文件继续增长时才分配一级间接索引块。
- 更大的文件才需要二级或更高级索引。
这种结构让元数据成本与文件大小共同增长。小文件不会承担为大文件准备的索引开销,大文件也不会受到固定指针数量的严格限制。
其代价是,访问文件后部的数据可能需要额外读取一层或多层索引块。不过这些索引块通常可以被缓存,因此实际访问不一定每次都产生完整的磁盘I/O。
4. inode与多级页表
inode索引与多级页表具有相似的结构思想,但服务对象不同。
| 对比点 | inode索引 | 多级页表 |
|---|---|---|
| 映射关系 | 文件逻辑块到存储数据块 | 虚拟页到物理页 |
| 索引依据 | 文件中的逻辑块编号 | 虚拟地址的各级索引 |
| 管理目标 | 定位文件内容 | 完成地址翻译和内存隔离 |
| 物理连续性 | 文件块可以离散 | 物理页可以离散 |
| 空间优化方式 | 按文件大小分配索引结构 | 按已使用的虚拟地址区域建立页表 |
二者的共同逻辑是:通过增加有限的间接访问,避免维护一个巨大而稀疏的扁平映射表。
❗ 本节核心结论: inode使用直接指针和多级间接指针,在小文件访问效率与大文件扩展能力之间取得平衡。
五、目录、文件名与路径解析
目录同样是一种文件,但其内容不是普通用户数据,而是一组目录项。
目录项至少记录:
1 | 文件名 + inode编号 |
例如:
1 | "a.txt" → inode 100 |
因此,目录不是一个物理上“装着文件内容的盒子”。它更接近一张名称索引表。子文件的数据仍然存放在各自的数据块中,目录只负责保存名字与inode之间的关系。
1. 路径是如何被解析的
访问/home/aster/demo.txt时,操作系统大致执行以下过程:
- 从根目录
/的inode开始。 - 读取根目录内容,查找名为
home的目录项。 - 获得
home对应的inode编号。 - 读取
home目录,查找aster。 - 获得
aster目录的inode编号。 - 读取
aster目录,查找demo.txt。 - 获得目标文件的inode。
- 根据inode中的索引信息定位数据块。
flowchart TD
R[根目录inode] --> H[查找home]
H --> HI[home目录inode]
HI --> A[查找aster]
A --> AI[aster目录inode]
AI --> F[查找demo.txt]
F --> FI[文件inode]
FI --> B[文件数据块]
路径解析本质上不是一次完成的字符串匹配,而是逐层读取目录、逐层完成“名字到inode”的转换。
普通目录的名字存放在其父目录中。根目录是整个路径系统的起点,不需要再由另一个父目录为其提供名字。
2. 目录大小取决于目录项,而不是子文件大小
一个包含100个小文件的目录,可能比一个只包含10部大型电影的目录本身更大。
原因在于目录保存的是:
- 文件名
- inode编号
- 文件类型等少量目录项信息
电影文件即使占用数十GB,在目录中也可能只对应一个很短的目录项。目录大小主要由项目数量、文件名长度和目录项结构决定,而不是由子文件内容总量决定。
3. 删除文件首先删除的是名字
从目录中删除文件时,最先消失的是:
1 | 文件名 → inode编号 |
的映射关系。
这不意味着数据必然立即被回收。文件系统还需要检查:
- inode是否仍被其他硬链接引用。
- 文件是否仍被某个进程打开。
- inode与数据块是否已经可以安全释放。
因此,文件名被删除、文件对用户不可见和底层数据块被重新分配,可能发生在不同时间。
❗ 删除文件的本质首先是解除名称引用,而不是立即擦除每一个数据字节。
六、文件系统在磁盘上的整体布局
文件系统不仅要保存普通文件,还要保存描述自身结构的元数据。格式化的主要作用,也不是简单地把设备全部清零,而是在设备上建立一套可以被文件系统识别和维护的布局。
一个简化的inode文件系统可能包含:
1 | 超级块 |
1. 超级块:文件系统的总说明书
超级块通常记录:
- 文件系统类型和魔法数字
- 文件系统块大小
- 总块数和空闲块数
- inode总数和空闲inode数
- 文件系统状态
- 创建、挂载等信息
魔法数字用于识别数据格式。操作系统读取分区中的特定位置后,可以依据魔法数字判断该区域是否属于自己支持的文件系统。
超级块描述了整个文件系统应该如何被解释。如果超级块严重损坏,操作系统可能无法确定inode表、位图和数据区域的位置,从而无法正常挂载文件系统。因此,很多文件系统会保存超级块的备份副本。
2. inode表:有限数量的文件档案
inode表是一组固定大小的inode记录。
如果文件系统在格式化时创建了5800万个inode,那么它最多只能同时容纳大约5800万个需要inode的对象。即使数据区仍然存在空闲空间,一旦inode耗尽,也无法继续创建新文件。
这解释了一种看似反常的现象:
磁盘容量明明没有用完,系统却提示无法创建文件。
此时耗尽的可能不是数据块,而是inode。
3. inode位图与数据块位图
位图使用一个二进制位表示一个对象是否空闲。
inode位图:
1 | 0:空闲inode |
数据块位图:
1 | 0:空闲数据块 |
创建文件时,文件系统从inode位图中寻找空闲inode;文件需要写入内容时,再从数据块位图中寻找空闲块。
这种机制与物理内存的位图分配器非常相似,只是管理对象由内存页变成了文件系统中的inode和数据块。
4. 创建文件时修改了什么
创建一个空文件通常至少涉及:
- 在inode位图中分配一个空闲inode。
- 初始化inode中的类型、权限、时间等元数据。
- 在父目录中增加目录项。
- 建立“文件名到inode编号”的映射。
当文件开始写入数据时,还需要:
- 从数据块位图中分配数据块。
- 在inode中记录数据块位置。
- 更新文件大小和时间。
- 必要时分配间接索引块。
因此,即使创建的只是一个空文件,也不是简单增加一个文件名,而是需要同时维护多种文件系统元数据。
❗ 本节核心结论: 文件系统必须记录自己的整体布局、已用资源和空闲资源;磁盘空间与inode数量是两类彼此独立的有限资源。
七、FAT:用簇链表连接文件数据
FAT是File Allocation Table,即文件分配表。它使用类似链表的方式组织分散的数据簇。
目录项中保存:
1 | 文件名 + 起始簇号 |
FAT表中的每一项则记录:
1 | 当前簇的下一个簇号 |
例如:
1 | 目录项:FILE1.DAT → 起始簇2 |
这表示文件的数据位于:
1 | 簇2 → 簇4 → 簇5 → 结束 |
读取文件时,系统需要:
- 从目录项获得起始簇。
- 读取当前簇的数据。
- 查询FAT表,获得下一个簇号。
- 继续读取,直到遇到文件结束标志。
1. FAT的优势
FAT结构简单,容易实现,也具有较强的跨平台兼容性,因此长期被用于U盘、存储卡和嵌入式设备。
文件增长时,只需要为文件分配新的簇,并把原链尾指向新簇,无须重新建立复杂的索引结构。
2. FAT的局限
FAT的主要问题来自链式结构。
- 要访问文件后部,通常需要沿簇链逐项查找。
- 文件越大,链越长,随机访问越不方便。
- 如果链中的某个表项损坏,后续簇可能全部失去联系。
- FAT表本身是整个文件系统的关键元数据,损坏后影响范围较大。
传统FAT通常保存两份FAT表,以便在主表损坏时尝试使用备份恢复。
3. FAT32的4GB单文件限制
FAT32的文件大小字段通常使用32位无符号数,最大能够表示:
1 | 2^32 - 1B |
即略小于4GiB。
因此,即使FAT32分区仍有大量空闲空间,也不能保存一个超过这一限制的普通文件。限制来自文件元数据中的大小字段,而不是来自分区剩余容量。
“FAT32”中的32也不意味着分区最大只能是32GB。它主要与FAT表项格式有关,不能与Windows某些格式化工具提供的32GB限制混为一谈。
4. exFAT的改进
exFAT针对更大容量的移动存储设备进行了扩展,包括:
- 扩大文件大小表示范围,支持超过4GB的文件。
- 使用空闲空间位图提高分配效率。
- 支持Unicode长文件名。
- 使用哈希值辅助目录查找。
- 使用校验信息提高元数据完整性。
exFAT仍保留了面向移动存储和跨平台使用的定位,但缓解了FAT32在大文件和大容量设备上的局限。
八、NTFS:以MFT统一组织文件元数据
NTFS是New Technology File System,是Windows系统中广泛使用的文件系统。它的核心结构是MFT,即Master File Table,主文件表。
MFT由大量记录组成,其中不仅包括普通文件和目录记录,还包括文件系统自身的元数据记录。
一个文件的MFT记录可以包含:
- 文件名
- 文件大小
- 权限
- 时间信息
- 数据所在的簇区段
- 其他属性
对于足够小的文件,数据本身甚至可以直接存放在MFT记录内部;较大的文件则由MFT记录描述其外部数据位置。
这种设计将文件视为一组属性,使NTFS能够通过较统一的结构管理名称、权限、内容和其他元数据。
1. 区段表示
如果文件占据一组连续簇,没有必要逐个保存:
1 | 100、101、102、103、104 |
可以使用一个区段表示:
1 | 起始簇:100 |
区段也称extent。对于连续性较好的大文件,区段能够显著减少定位信息的数量。
文件发生碎片化后,则需要用多个区段描述:
1 | 起始簇100,长度5 |
因此,与FAT逐簇建立链表相比,区段更适合描述大段连续空间。
2. 为什么文件系统偏爱B树和B+树
文件系统中的查找成本主要来自存储I/O,而不是CPU完成一次关键字比较所需的时间。
普通二叉树的每个节点只有少量分支,数据量增大后树会变得较高。B树或B+树的一个节点可以容纳大量关键字和子指针,因此具有很高的分支因子。
| 结构 | 单个节点分支数 | 树高 | 典型I/O次数 |
|---|---|---|---|
| 二叉树 | 最多2个 | 较高 | 较多 |
| B树或B+树 | 数十至数百个 | 较低 | 较少 |
如果树的一个节点恰好对应一个磁盘块,那么一次读取就可以获得大量索引信息。树越矮,完成查找需要读取的磁盘块就越少。
❗ B树的核心价值并不只是渐进复杂度,而是用高分支因子减少昂贵的存储I/O。
3. MFT镜像与日志
NTFS会为部分重要MFT信息保存镜像,以降低关键元数据损坏后整个文件系统无法使用的风险。
它还使用日志记录元数据修改。若系统在更新目录、分配空间或修改MFT时突然断电,日志可以帮助文件系统判断哪些操作已经完成、哪些操作需要回滚或重新执行。
日志通常不能保证用户文件的所有内容都不丢失,但可以显著降低文件系统结构陷入不一致状态的概率。
4. MFT如何找到自身
MFT本身也被视为一个文件,通常记为$Mft。这会产生一个看似循环的问题:
1 | 需要先读取MFT才能找到文件 |
NTFS通过自举解决这一问题:
- 文件系统引导区域保存MFT初始位置等基础信息。
- 系统根据这些固定信息读取MFT的起始部分。
- MFT中的
$Mft记录再描述MFT自身剩余部分的位置。
系统只需要在固定位置保存一小部分启动信息,之后便可以进入由MFT统一描述的正常文件系统结构。
❗ 本节核心结论: NTFS以MFT统一记录文件属性,使用区段和树形索引提高大文件及大目录的访问效率,并通过镜像和日志增强元数据可靠性。
九、inode、FAT与NTFS的设计差异
三类文件系统采取了不同的数据定位方式。
| 对比点 | inode文件系统 | FAT | NTFS |
|---|---|---|---|
| 文件核心记录 | inode | 目录项和FAT表 | MFT记录 |
| 文件名位置 | 目录项 | 目录项 | MFT属性或目录索引 |
| 数据定位方式 | 直接指针和多级索引 | 簇链表 | 区段、属性和树形结构 |
| 随机访问能力 | 较好 | 大文件后部访问较慢 | 较好 |
| 结构复杂度 | 中等 | 较低 | 较高 |
| 空闲空间管理 | 常见位图 | FAT或辅助结构 | 位图等结构 |
| 可靠性机制 | 取决于具体实现 | FAT备份 | MFT镜像和日志 |
| 典型使用环境 | Linux等类Unix系统 | 移动设备、兼容场景 | Windows系统 |
inode和FAT之间最明显的区别,是索引分配与链式分配的区别。
| 对比点 | inode索引 | FAT链表 |
|---|---|---|
| 基本思路 | 从索引结构定位数据块 | 从起始簇沿链寻找后续簇 |
| 随机访问 | 可以计算并查找对应索引项 | 通常需要沿链遍历 |
| 文件增长 | 增加数据块和必要的索引块 | 将新簇接到链尾 |
| 损坏影响 | 一个索引项影响其对应范围 | 链中断可能使后续簇全部失联 |
| 实现复杂度 | 较高 | 较低 |
这几种方案并不存在脱离使用环境的绝对优劣。
- FAT结构简单、兼容性强,适合移动介质。
- inode分级索引适合大量不同大小文件,并具有较好的随机访问能力。
- NTFS以更复杂的元数据和可靠性机制换取功能完整性。
文件系统设计始终是在实现复杂度、访问效率、空间开销、可靠性和兼容性之间作出权衡。
十、文件系统如何解释日常现象
1. 为什么1TB硬盘只显示约931GB
这一现象首先来自十进制和二进制单位差异。
厂商通常按照十进制计算:
1 | 1TB = 10^12B |
而许多操作系统界面过去按照二进制单位换算:
1 | 1GiB = 2^30B |
因此:
1 | 10^12 ÷ 2^30 ≈ 931.3 |
厂商标称1TB的设备,对应约931.3GiB。有些界面虽然写作“GB”,实际使用的却是GiB换算方式。
除此之外,格式化还需要占用一部分空间保存:
- 超级块
- 分配位图
- inode表或MFT
- 文件系统日志
- 备份元数据
- 保留区域
因此需要区分两个不同问题:
1 | 1TB变成约931GiB |
2. 为什么文件大小与占用空间不同
“文件大小”表示文件包含的有效字节数量。
“占用空间”表示文件系统实际为其分配的存储块总量。
假设文件系统块大小为4KB,一个605B的文件通常也需要占用完整的数据块:
1 | 文件大小:605B |
剩余空间属于块内部无法分配给其他普通文件的区域,称为内部碎片。
一个极小文件还可能同时消耗:
- 一个inode或MFT记录
- 一个目录项
- 位图中的分配标记
- 日志中的元数据记录
因此,“文件内容只有1B”并不意味着其全部存储成本只有1B。
某些文件系统可能通过小文件内联、压缩、稀疏文件等机制改变实际占用,但这些属于额外优化,不能否定按块分配的基本原则。
3. 为什么复制大量小文件特别慢
复制十万个小文件与复制一个同样总大小的大文件,数据总量可能相同,但文件系统工作量完全不同。
复制每个小文件都可能涉及:
- 路径查找。
- 打开源文件。
- 创建目标目录项。
- 分配inode或MFT记录。
- 分配数据块。
- 更新多个位图或索引结构。
- 读取与写入数据。
- 更新时间信息。
- 关闭文件。
- 提交或记录元数据修改。
如果文件数量为十万,这套流程就要重复十万次。小文件还可能分散在不同位置,形成大量零碎I/O。
打包后再复制,则更接近传输一个连续的大文件:
- 只需创建少量文件系统元数据。
- 可以进行较长的顺序读写。
- I/O请求更容易合并。
- 如果同时压缩,实际传输数据量还可能减少。
❗ 大量小文件复制缓慢的主要原因,不是文件内容更多,而是元数据操作次数和离散I/O次数更多。
十一、一次文件读取的完整逻辑
以inode文件系统读取/home/a.txt为例,完整过程可以概括为:
1 | 从根目录inode开始 |
这一过程揭示了文件系统的真正工作方式。
应用程序发出的请求是:
1 | 读取/home/a.txt中的一段内容 |
存储设备能够理解的请求却是:
1 | 读取若干编号的数据块 |
文件系统及其上下层软件所做的,就是逐步完成名称、路径、inode、逻辑偏移、数据块和硬件请求之间的翻译。
结论
文件系统的本质,是在块设备提供的原始空间之上建立一套持久化的数据组织规则。
它需要同时解决几个彼此关联的问题:
- 如何把分散的数据块组织成逻辑连续的文件。
- 如何通过文件名和路径找到文件。
- 如何记录文件大小、权限、时间和所有者等元数据。
- 如何判断哪些inode和数据块已经使用。
- 如何支持大小差异巨大的文件。
- 如何在设备损坏或异常断电后维护结构一致性。
inode、FAT和NTFS分别代表了三种不同的组织思路:
- inode通过直接指针和多级间接索引定位数据块。
- FAT通过簇链表串联文件内容。
- NTFS通过MFT、区段和树形索引统一管理文件属性与数据位置。
它们虽然在数据结构上差异明显,却都完成了同一项抽象:把一大片没有名称和层级的编号存储块,转化成用户可以理解和操作的文件世界。
❗ 文件并不是存储设备天然提供的实体,而是文件系统利用元数据、索引、目录和分配结构构造出来的逻辑对象。




