考研学习
知识点讲义操作系统

第 4 章 文件管理

408 操作系统第 4 章 文件管理复习讲义,涵盖核心概念、重点考点与典型题型。

Last updated on

先把整章压缩成一句话:

用户写文件名
   ↓
操作系统查目录
   ↓
目录项找到 inode / FCB
   ↓
inode / FCB 找到文件的磁盘块
   ↓
根据文件物理结构访问真正的数据

如果这条链理解透了,第 4 章的大部分知识就只是“这条链的不同环节怎样实现”。

一、本章整体框架

模块核心问题考试重要度
文件基本概念什么是文件、文件有哪些属性★★
文件逻辑结构用户眼里的文件如何组织★★★
文件物理结构数据块实际怎样放在磁盘★★★★★
FCB / inode操作系统怎样描述一个文件★★★★★
目录结构文件名怎样找到文件★★★★
文件操作create/open/read/write/close/delete 怎样实现★★★★
文件共享硬链接、软链接★★★★★
文件保护谁能读、写、执行★★★
文件系统布局磁盘与内存中的文件系统结构★★★★
空闲空间管理哪些磁盘块还能使用★★★★★
VFS如何统一 ext4、NTFS、FAT 等★★★★
挂载一个文件系统怎样接入目录树★★★

二、首先搞懂:文件到底是什么?

文件是存放在持久性存储设备上的信息集合。

从用户角度看,你看到的是:

考研资料.pdf
main.c
hello.txt
video.mp4

磁盘实际上完全不知道这些“文件名”是什么意思,它只知道:

0号块
1号块
2号块
3号块
……

所以文件系统做的本质工作,是把“零散的磁盘块”抽象为用户可以理解的“文件和目录”。

一个文件可以理解为:

文件
├── 文件内容
└── 文件元数据

所谓元数据,就是“描述文件的数据”,包括文件类型、大小、位置、所有者、权限、创建/修改时间以及数据块位置等。

三、文件的逻辑结构

这里一定要先区分两个概念:

逻辑结构回答:

用户怎么看这个文件?

物理结构回答:

这个文件的数据块在磁盘上实际上怎么放?

资料将逻辑文件分成无结构文件和有结构文件。

1. 无结构文件:流式文件

最简单。

操作系统认为文件就是:

byte0 byte1 byte2 byte3 byte4 ...

没有“第几条记录”的概念。

例如文本文件、程序文件、可执行文件,本质上都可以视为字节流。

访问依靠文件指针:

当前读写位置
        ↓
... A B C D E F G ...
        ↑

读一次后,文件指针继续向后移动。

这种结构最大的优点是简单、通用。

四、有结构文件

又叫记录式文件。

例如学生数据:

001 张三 90
002 李四 85
003 王五 92

每一行为一条记录。

记录又分为定长记录和变长记录。

如果每条记录长度固定,就可以直接计算第 k 条记录的位置;若长度不固定,一般无法简单通过乘法得到目标位置。

有结构文件进一步有三种典型组织形式:

类型核心思想
顺序文件一条记录接一条记录
索引文件建索引直接定位记录
索引顺序文件分组 + 索引 + 组内查找

1. 顺序文件

记录顺序排放。

又分成“串结构”和“顺序结构”。

串结构只是按写入时间排列:

记录 A
记录 C
记录 B
记录 F

关键字不一定有序。

顺序结构则按照关键字排序:

001
002
003
004
005

如果同时满足记录定长 + 按关键字有序,就特别适合快速检索。

2. 索引文件

相当于给记录建立一个“目录”。

索引
001 → 记录位置
002 → 记录位置
003 → 记录位置

不需要每次从头查。

代价是:

额外占用索引空间。

这和数据库索引的思想完全一致。

3. 索引顺序文件

这一点题库专门考了。

它和数据结构中的分块查找几乎是一回事:

索引
 ↓
确定在哪一组
 ↓
进入该组
 ↓
组内查找

最重要的性质是:

组间必须有序,组内可以无序。

配套模拟题就是直接考这一点,答案为“组间有序,组内可以无序”。

五、★★★★★ 本章最核心:文件的物理结构

这是第 4 章最重要的部分之一。

资料对不同物理结构的特点与比较标出了 2009、2011、2013、2020 等统考考点,连续分配又在 2011、2012、2014 等年份出现。

文件最终一定要被切成磁盘块。

假设:

块大小 = 4KB
文件大小 = 10KB

至少需要:

个磁盘块。

问题变成:

这 3 个块到底怎么分配?

三大方法:

连续分配
链接分配
索引分配

六、连续分配

例如文件 A 占:

20 21 22 23 24

目录只需记:

起始块 = 20
长度 = 5

如果文件的第一个逻辑块编号为 0,那么第 i 个逻辑块的位置直接是:

所以它天然支持随机访问。

例如起始块是 100,要找逻辑第 25 块:

直接访问 125 号磁盘块即可。

资料指出连续分配支持顺序和直接访问,而且由于数据块连续,顺序访问速度很快。

为什么快?

磁盘:

20 → 21 → 22 → 23 → 24

磁头基本不需要到处跑。

最大问题

不是“读慢”,而是:

扩展困难。

例如:

A:20 21 22
B:23 24 25

A 想再加一块,但 23 已经属于 B。

怎么办?

要么:

搬整个 A

要么根本扩不进去。

此外连续分配还会产生外部碎片。

所以记住:

连续分配 = 最快,但最不灵活。

七、链接分配

文件的磁盘块可以随便放:

9 → 27 → 3 → 41 → 15

每个块记录下一个块在哪里。

这样文件增长就简单很多:

原来:
9 → 27 → 3

新增:
9 → 27 → 3 → 88

完全不用找连续空间。

因此没有连续分配那种外部碎片问题。

但有一个严重问题。

假如你要访问第 100 个块:

第1块
 ↓
第2块
 ↓
第3块
 ↓
……
 ↓
第100块

必须沿链逐个找。

所以:

普通隐式链接适合顺序访问,不适合随机访问。

资料的比较表甚至直接总结为:连续分配访问第 n 条记录通常只需一次磁盘访问;普通链接分配可能需要沿链访问到第 n 块。

八、FAT:显式链接

FAT = File Allocation Table,文件分配表。

它是对链接分配的重要改进。

原本:

数据块9中:next = 27
数据块27中:next = 3
数据块3中:next = 41

现在把这些 next 信息全部抽出来,放到 FAT:

FAT[9]  = 27
FAT[27] = 3
FAT[3]  = 41
FAT[41] = EOF

这样文件数据块本身就不用保存 next。

更重要的是:

FAT 通常被加载进内存。

于是查链:

9 → 27 → 3 → 41

是在内存中的 FAT中完成,而不是每走一步都访问磁盘。

资料强调 FAT 的表项和磁盘块基本是一一对应的,而且 FAT 还可以用特殊值标记空闲块,因此它既负责文件链,也能辅助空闲空间管理。

FAT 的代价

磁盘越大:

磁盘块越多
   ↓
FAT表项越多
   ↓
FAT越大
   ↓
常驻内存成本越高

所以 FAT 系统后来引入“簇”。

多个扇区组成一个簇,把分配单位变大。

例如:

原来:1个FAT项 ↔ 1个扇区
现在:1个FAT项 ↔ 8个扇区

FAT 表项数量明显减少。

但簇变大之后容易产生更多内部碎片。

九、★★★★★ 索引分配

这是考研最值得掌握的文件分配方式。

核心思想:

不把“下一块地址”分散在各个数据块中,而是单独建立一个索引块。

假设一个文件的数据块是:

13
95
27
8
44

索引块:

0 → 13
1 → 95
2 → 27
3 → 8
4 → 44

要访问文件逻辑第 3 块:

索引表[3] → 8

直接知道数据在 8 号磁盘块。

所以:

索引分配同时实现了离散分配 + 随机访问。

十、单级索引最大文件长度怎么算?

这是非常标准的一类计算题。

假设:

磁盘块大小 = B
一个磁盘地址占 p 字节

一个索引块能装的地址数:

因此单级索引能表示的数据量:

即:

资料使用的经典例子:

块大小 = 4KB
地址项 = 4B

一个索引块能够容纳:

个磁盘块地址。

所以最大文件长度:

十一、多级索引

单级索引最多 4MB,不够怎么办?

再给“索引块”建一个索引。

一级索引块
       ↓
多个二级索引块
       ↓
大量数据块

这和第 3 章的多级页表非常像。

仍取:

块大小 = 4KB
地址 = 4B

每个索引块可容纳:

个地址。

二级索引可管理的数据块数量:

因此最大文件:

三级则近似:

资料正是用这个例子解释多级索引。

十二、★★★★★ 混合索引

为什么不所有文件都用三级索引?

因为现实中有大量:

1KB
5KB
20KB
50KB

的小文件。

假如访问一个 5KB 文件都要:

读一级索引
↓
读二级索引
↓
读三级索引
↓
读数据

显然非常浪费。

所以 UNIX 的思想是:

小文件 → 直接地址
中型文件 → 一级间接
大文件 → 二级间接
超大文件 → 三级间接

也就是混合索引。

资料中的经典 UNIX inode 示例包含 13 个地址项:

i.addr(0) ~ i.addr(9)  :10个直接地址

i.addr(10)              :一级间接地址
i.addr(11)              :二级间接地址
i.addr(12)              :三级间接地址

十三、混合索引容量计算——必须会

仍然假设:

块大小 = 4KB
地址项 = 4B

每个索引块:

个地址。

10 个直接地址

一个一级间接地址

一个二级间接地址

一个三级间接地址

因此总最大文件大小为:

资料将混合索引相关计算列为 2010、2015、2018、2022 等统考考点,属于本章最应该反复做题的部分之一。

十四、另一个高频:访问一个数据块要几次磁盘 I/O?

关键看:

inode 是否已经在内存。

若 inode 已在内存,不算读取 inode 的次数。

直接地址

inode:

inode → 数据块

只读数据块:

一级间接

inode
 ↓
一级索引块
 ↓
数据块

需要:

二级间接

inode
 ↓
一级索引块
 ↓
二级索引块
 ↓
数据块

需要:

三级间接

需要:

题库就有一道非常典型的题:inode 已在内存,12 个直接指针,块大小 4KB;读取第 9876 字节走直接地址,需要 1 次磁盘访问;读取第 543210 字节落在一级间接区,需要先读一级索引块再读数据块,共 2 次。

所以见到这种题先问:

① inode在不在内存?
② 目标字节属于第几个数据块?
③ 落在直接/一级/二级/三级哪个区域?

基本就做出来了。

十五、三种物理分配方式最后对比

性质连续分配链接分配索引分配
是否要求连续空间是否否
顺序访问很快可以可以
随机访问很快隐式链接很差很好
外部碎片有无无
文件扩展困难容易容易
额外空间小指针索引块
典型思想数组链表索引表

可以直接类比数据结构:

连续分配 ≈ 顺序表
链接分配 ≈ 链表
索引分配 ≈ 索引查找

十六、★★★★★ FCB:操作系统怎么知道“这是一个文件”?

假如磁盘上只有:

100号块
231号块
871号块

操作系统并不知道:

这三块属于 /home/a.txt。

所以必须有一个数据结构描述文件。

这就是:

FCB:File Control Block,文件控制块。

FCB 是文件存在和管理的重要依据。

资料中的 FCB 主要包含:

类型内容
基本信息文件名、类型、大小、位置
存取控制所有者、权限
使用信息创建时间、修改时间等

因此可以理解:

文件内容
     ↑
     │
FCB告诉OS数据在哪里
     ↑
     │
文件名

十七、★★★★★ inode 为什么出现?

如果每个目录项里都塞一个完整 FCB:

a.txt + 文件大小 + 权限 + 地址 + 时间 + ...
b.txt + 文件大小 + 权限 + 地址 + 时间 + ...
c.txt + 文件大小 + 权限 + 地址 + 时间 + ...

一个目录项会非常大。

但我们查目录时真正首先需要比较的只是:

文件名。

于是 UNIX 把:

文件名

和:

文件属性
文件位置
权限
大小
……

拆开。

目录变成:

文件名    inode号

a.txt     15
b.txt     27
c.txt     81

然后:

inode 15 → a.txt的真正属性和磁盘块地址

所以:

目录项主要负责“名字 → inode”;inode 负责描述真正的文件。

这是一条非常重要的理解。

资料把目录项结构相关分析列为 2020、2022 考点。

十八、经典 inode 目录检索计算

题库中的经典题:

磁盘块 = 512B
FCB = 64B
文件名 = 6B
inode编号 = 2B
目录有256项

没有 inode

一个块能放:

个目录项。

256 个目录项需要:

个磁盘块。

顺序查找,平均:

次磁盘访问。

引入 inode

目录项只需要:

6B文件名 + 2B inode号

所以一项:

每个盘块可以放:

项。

256 项只需:

个盘块。

平均检索目录:

找到目录项后,还要读 inode:

因此减少:

次。

这正是配套题的答案。

这种题的本质

不是考 inode 定义。

而是在考:

inode 把“大量暂时没用的文件属性”从目录项拆出去了,所以目录项更小,一个磁盘块能装更多目录项,目录查找 I/O 更少。

十九、目录到底是什么?

目录本身也可以看成一种特殊文件。

它负责建立:

文件名 → 文件控制信息

的映射。

目录管理最核心目标:

按名存取。

即用户给出:

/home/tom/a.txt

系统能最终定位到 a.txt 的 inode。

二十、目录结构的发展

单级目录

所有文件放一起:

/
├── a.txt
├── b.txt
├── c.txt
└── d.txt

简单,但不同用户不能很好地重名。

两级目录

首先按用户分。

MFD
├── 用户A → UFD_A
└── 用户B → UFD_B

用户 A 可以有:

a.txt

用户 B 也可以有:

a.txt

解决重名问题。

但每个用户内部还是扁平目录。

二十一、树形目录

现代系统最常见。

/
├── home
│   ├── tom
│   │   ├── a.txt
│   │   └── b.txt
│   └── jack
├── bin
└── etc

资料强调树形目录中的两个路径概念。

绝对路径

从根开始:

/home/tom/a.txt

相对路径

从当前工作目录开始。

假如:

当前目录 = /home/tom

那么访问:

docs/a.txt

实际上是:

/home/tom/docs/a.txt

为什么要有当前目录?

因为如果每次都必须从根目录开始:

/
↓
home
↓
tom
↓
docs
↓
a.txt

路径解析很长。

设定当前目录后,可以减少重复目录检索。

二十二、★★★★★ 文件打开 open:一定要理解全过程

这是本章非常重要的一条过程题。

资料明确标出了:

文件打开:2014、2017、2020
文件关闭:2023
文件名与文件描述符:2012、2017、2024

假设执行:

open("/home/tom/a.txt")

系统先解析路径:

/
↓
home
↓
tom
↓
a.txt

找到目录项:

a.txt → inode 57

然后查系统打开文件表。

如果 inode 57 对应的文件还没打开:

磁盘 inode
     ↓
读入内存
     ↓
创建系统打开文件表项

如果已经有人打开:

直接复用系统打开文件表项
open count++

然后再:

给当前进程建立一个进程打开文件表项

最后返回一个整数:

fd

这就是文件描述符。

完整链条:

文件名
 ↓
目录项
 ↓
inode
 ↓
系统打开文件表
 ↓
进程打开文件表
 ↓
文件描述符 fd

二十三、系统打开文件表 vs 进程打开文件表

这个容易混。

数据放哪里
文件本身共享属性系统打开文件表
打开计数系统打开文件表
进程自己的访问模式进程打开文件表
进程自己的读写状态进程打开文件表
文件描述符对进程打开文件表项的索引

资料使用“两级打开文件表”来解释多个进程访问同一文件的共享和隔离。

二十四、为什么打开以后不再使用文件名?

第一次:

open("/home/tom/a.txt")

需要做:

路径解析
↓
目录查找
↓
inode查找

很贵。

成功以后返回:

fd = 3

后续:

read(3, ...)
write(3, ...)
close(3)

直接通过 fd 查内存中的打开文件表即可。

所以:

文件名主要用于 open 阶段;文件打开后主要使用文件描述符。

这是考试非常喜欢设陷阱的地方。

二十五、close 的过程

例如三个进程都打开文件:

open count = 3

一个进程关闭:

3 → 2

第二个关闭:

2 → 1

最后一个关闭:

1 → 0

只有到:

open count = 0

系统才能把相应的系统打开文件表项释放。

因此:

close() 并不是删除磁盘上的文件。

它只是关闭这个打开实例。

二十六、create / delete / read / write

create

核心过程可以理解成:

检查路径、权限、重名
 ↓
分配 inode / FCB
 ↓
需要时分配数据块
 ↓
目录中加入:
文件名 → inode号
 ↓
更新空闲块、inode等元数据

read

已经打开时可以理解为:

fd
 ↓
打开文件表
 ↓
inode
 ↓
根据当前文件指针确定逻辑块
 ↓
物理分配结构找到磁盘块
 ↓
读入内存
 ↓
更新文件指针

write

类似:

fd
 ↓
定位文件
 ↓
根据写指针找到数据块
 ↓
写数据

若空间不足:

申请新的磁盘块
 ↓
修改 inode / 索引结构
 ↓
修改文件大小

资料对读写过程也明确强调了“根据当前读写指针定位并更新指针”。

二十七、★★★★★ delete 为什么比想象复杂?

删除绝不是简单:

把文件名删掉

资料将文件删除过程标注为 2013、2021 考点。

真正过程大致是:

找到目录项
 ↓
找到 inode
 ↓
检查硬链接计数
 ↓
移除目录项
 ↓
若引用已经归零
     ↓
释放 inode
     ↓
释放数据块
     ↓
更新空闲空间信息

最关键的问题就是:

这个文件有没有其他硬链接?

于是自然进入下一大高频考点。

二十八、★★★★★ 硬链接

假设:

A目录:
hello → inode 25

B目录:
test → inode 25

二者虽然文件名不同:

hello
test

但:

都指向 inode 25

所以实际上是同一个文件。

hello ─┐
       ├→ inode25 → 数据块
test ──┘

inode 中维护一个链接计数:

count = 2

资料把硬链接列为 2009、2017 考点。

二十九、删除一个硬链接会发生什么?

当前:

A → inode25
B → inode25

count = 2

A 删除自己的文件名:

A ✕
B → inode25

count = 1

磁盘数据:

不能删除。

因为 B 还在用。

只有最后一个链接也删除:

count = 0

才能真正:

释放inode
+
释放文件数据块

因此记住:

硬链接删除的是“一个名字”,不是立即删除“数据”。

三十、★★★★★ 软链接

软链接完全不同。

假设真正文件:

/home/tom/a.txt

软链接文件:

b.txt

b.txt 自己有:

自己的inode
自己的文件内容

其内容类似:

/home/tom/a.txt

所以访问:

b.txt

实际上是:

找到b.txt
 ↓
读取里面保存的路径
 ↓
重新解析 /home/tom/a.txt
 ↓
找到真正文件

资料把软链接相关原理标为 2009、2021 考点。

三十一、硬链接和软链接对比

项目硬链接软链接
本质新目录项指向同一 inode新建一个保存路径的文件
inode相同不同
数据副本只有一个软链接本身另有少量数据
原文件名删除后一般仍可访问可能变成悬空链接
查找速度快较慢
删除机制count 归 0 才真正删除不影响目标 inode 的链接计数
实现思想指针共享路径共享

一句话:

硬链接:指向文件本体
软链接:记住怎么去找文件

三十二、文件保护

文件共享之后,就必须解决:

谁有权访问?

常见权限包括:

读
写
执行
添加
删除
列目录

资料指出访问控制是文件保护的主要方式,同时口令保护与加密可以作为补充。

三十三、ACL

ACL:

Access-Control List,访问控制列表。

思想就是:

张三:读、写
李四:读
王五:无权限

完整 ACL 很灵活,但用户多了列表会很长。

因此 UNIX/Linux 常进一步概括为:

owner
group
others

再给每组:

r
w
x

例如:

rwxr-xr--

理解为:

owner  → rwx
group  → r-x
others → r--

三十四、口令保护和加密保护

口令:

访问文件
 ↓
输入正确口令
 ↓
允许访问

优点是简单,缺点是安全性有限。

加密:

明文
 ↓ key
密文

访问时再解密。

优点是保密性更好,缺点是存在计算开销。

但要特别注意:

它们并不能很好地区分“可以读但不能写”这种精细权限。

所以不能代替 ACL。

三十五、★★★★★ 文件系统在磁盘中的布局

这是 2022 考纲扩展后很重要的一部分。

资料中给出的典型磁盘结构可以理解为:

磁盘
│
├── MBR
│
└── 分区
    ├── boot block
    ├── super block
    ├── 空闲空间信息
    ├── inode区
    ├── 根目录
    └── 文件/目录数据区

三十六、超级块 superblock

非常重要。

超级块不是描述“某一个文件”。

而是:

描述整个文件系统。

例如记录:

文件系统总块数
块大小
空闲块数量
空闲inode数量
文件系统状态

所以常见陷阱是:

inode → 描述一个文件
superblock → 描述整个文件系统

文件系统挂载时,超级块的重要信息会读入内存。

三十七、内存中的文件系统结构

磁盘上的结构负责持久保存。

运行过程中,操作系统为了性能,会把大量文件系统信息缓存到内存。

例如:

已挂载文件系统信息
inode缓存
目录项缓存
打开文件表
缓冲区

这就是为什么:

第一次打开文件较慢
以后访问可能更快

因为很多信息不必重新访问磁盘。

三十八、★★★★★ 外存空闲空间管理

删除文件之后:

原先属于该文件的磁盘块
          ↓
        变空闲

操作系统必须记录:

哪些块有人用
哪些块没人用

经典方法是:

方法核心思想
空闲表法记录连续空闲区
空闲链表法空闲块串成链
位示图法每个块对应一个 bit
成组链接法分组管理大量空闲块

三十九、★★★★★ 位示图

例如:

0 1 1 0 0 1 0 ...

可以约定:

0 = 空闲
1 = 已分配

注意:

0/1 的含义本身不是本质,题目也可能反过来规定。

重要的是根据题目约定判断。

如果有 N 个磁盘块,位图需要:

例如 8192 个块:

四十、位示图行列号计算

假设:

每行 m 位
块号 b
编号从0开始

那么:

配套题:

每行32位
盘块号4567

则:

所以:

第142行,第23列

题库答案正是如此。

这类题一般很送分,注意编号是否从 0 开始即可。

四十一、成组链接法

UNIX 的经典方法。

为什么不用单纯的空闲链表?

如果有几百万个空闲块:

1 → 2 → 3 → 4 → …… → 1000000

管理效率不够理想。

成组链接的思想是:

一组一组管理。

例如每组 100 个:

第一组:100个块
        ↓
其中某块保存下一组100个块的块号
        ↓
第二组
        ↓
第三组

同时,当前最常用的一组块号会放在内存中的“空闲盘块号栈”。

四十二、成组链接的分配过程

假设内存里现在有:

空闲盘块号栈
┌───────┐
│ 201   │
│ 202   │
│ ...   │
│ 299   │
│ 300   │
└───────┘

正常时:

从栈里取一个块

当这一组快用完:

读特殊索引块
 ↓
获得下一组空闲块号
 ↓
装入内存栈

继续分配。

四十三、成组链接的回收

普通情况下:

释放一个块
 ↓
把块号压入空闲块号栈

但如果:

栈已经满

怎么办?

资料给出的做法是:

把当前栈中的块号信息
       ↓
写进刚刚回收的那个盘块
       ↓
让该盘块变成新的索引块

然后重新开始一组。

你不需要死背图,只要理解:

成组链接 = 用少量内存保存当前一组,用磁盘块保存下一组信息。

四十四、★★★★★ VFS:虚拟文件系统

这是近年来越来越值得重视的内容,资料明确标注 VFS 原理与特点为 2025 考点。

现实中:

Linux ext4
Windows NTFS
U盘 FAT32
光盘 ISO9660
网络文件系统

结构全不一样。

如果应用程序必须写:

ext4_open()
ntfs_open()
fat_open()

会非常麻烦。

所以增加:

             用户程序
                 │
        open/read/write
                 │
                VFS
       ┌─────────┼─────────┐
      ext4      NTFS       FAT

用户只调用统一接口:

open()
read()
write()
close()

底层到底是 ext4 还是 NTFS,由 VFS 帮你转发。

所以:

VFS 的核心不是存数据,而是提供统一抽象接口。

配套题问“VFS 的主要作用是什么”,正确答案就是:

为不同类型文件系统提供统一的抽象接口。

四十五、VFS 的四种核心对象

资料采用四类对象来解释。

对象可以怎么理解
superblock 对象一个已挂载文件系统
vnode 对象一个文件/目录的统一抽象
dentry 目录项对象路径中的一个名字
file 文件对象某进程打开文件后的实例

尤其注意:

vnode ≠ inode。

inode 是某种具体文件系统中的实际文件元数据结构。

vnode 是:

VFS 为了把不同文件系统统一起来建立的内存抽象。

四十六、用 write 理解 VFS 全链路

进程执行:

write(fd, buf, n)

大致过程:

write(fd)
   ↓
根据fd找到文件对象
   ↓
找到vnode
   ↓
VFS根据vnode中的操作函数
   ↓
调用具体文件系统的write
   ↓
缓冲区
   ↓
设备驱动
   ↓
磁盘

资料就是用 write() 解释 VFS 调度过程。

所以:

VFS = 统一接口层

而不是:

VFS = 磁盘上的某一种文件系统

资料特别强调:

VFS 本身并不是真正的磁盘文件系统,它主要作为内存中的统一抽象存在。

四十七、文件系统挂载 mount

假如 U 盘里自身有一棵目录树:

/
└── usr
    └── bin
        └── vim

现在把这个文件系统挂载到:

/media/disk

那么系统统一目录树里变成:

/media/disk/usr/bin/vim

这正是配套题的答案。

所以挂载可以理解成:

把另一个文件系统的根,接到当前目录树的某个目录上。

四十八、本章最容易混淆的几个概念

概念 A概念 B区别
文件逻辑结构文件物理结构用户怎么看 vs 磁盘怎么放
FCBinodeinode 是把文件名等与主要描述信息分离后的典型实现
目录项inode目录项主要完成名字映射,inode 描述文件
文件名文件描述符open 前找文件 vs open 后操作文件
文件打开计数硬链接计数当前有多少打开引用 vs 有多少目录项指向 inode
连续分配链接分配连续块 vs 离散链
链接分配索引分配逐块找下一块 vs 集中索引
硬链接软链接同 inode vs 保存路径
inodevnode具体文件系统元数据 vs VFS 的统一内存抽象
superblockinode整个文件系统 vs 单个文件
VFSext4/NTFS抽象层 vs 真正文件系统
opencreate打开已有文件 vs 创建文件
closedelete关闭打开实例 vs 删除文件目录引用/数据

四十九、第 4 章计算题统一方法

这一章真正需要“算”的主要有三类。

A. inode / 目录项计算

先算:

然后:

顺序查找平均磁盘访问次数,题目若假设等概率,通常再根据目录占用块数分析平均访问位置;若 inode 不在同一目录项中,还应考虑找到目录项后读取 inode 的 I/O。

B. 多级索引计算

第一步:

第二步:

直接地址:

一级间接:

二级间接:

三级间接:

总容量就是相关部分相加。

这是本章最值得练熟的公式框架。

C. 位示图

如果每行 m 位,块号从 0 开始:

如果题目从 1 开始编号,则必须相应调整,不能机械套公式。

五十、最后给你建立一条“真正理解文件系统”的全过程

假设程序:

fd = open("/home/tom/a.txt", READ);
read(fd, buf, 100);
close(fd);

你脑中应该自动出现:

open("/home/tom/a.txt")
          │
          ▼
解析路径
/ → home → tom → a.txt
          │
          ▼
找到目录项
a.txt → inode 57
          │
          ▼
读入/查找 inode
          │
          ▼
检查权限
          │
          ▼
建立系统打开文件表项
          │
          ▼
建立进程打开文件表项
          │
          ▼
返回 fd
          │
          ▼
read(fd)
          │
          ▼
找到文件对象/打开文件表
          │
          ▼
根据当前文件指针确定逻辑块
          │
          ▼
根据连续/链接/索引结构
把逻辑块映射到磁盘物理块
          │
          ▼
访问磁盘块
          │
          ▼
数据进入内存
          │
          ▼
更新文件指针
          │
          ▼
close(fd)
          │
          ▼
删除进程表项
open count--
          │
          ▼
若降到0,释放系统打开文件表相关项

而如果最后执行的是:

unlink("/home/tom/a.txt")

又要走:

目录项
 ↓
inode
 ↓
硬链接计数--
 ↓
是否为0?
 ├─ 否 → 数据继续保留
 └─ 是 → 回收inode和磁盘块

如果磁盘块被回收:

位示图修改
或
空闲链表修改
或
成组链接结构更新

这时可以发现,第 4 章看似知识点很多,其实从头到尾是在描述同一个文件的一生:

创建
↓
目录登记
↓
inode描述
↓
磁盘分配
↓
open
↓
read/write
↓
共享与保护
↓
close
↓
delete
↓
释放磁盘空间

这条主线比单独背几十个概念有效得多。

五十一、考研复习时建议优先掌握什么

按你这套资料里的考点追踪和题库分布,复习优先顺序建议是:

  1. 第一梯队:必须达到“看到题立即会算”——连续/链接/索引分配;单级、多级、混合索引最大文件长度;直接/一级/二级/三级索引磁盘访问次数;FCB/inode 目录检索计算;硬链接计数;位示图计算。
  2. 第二梯队:必须达到“能完整讲过程”——open、close、read、write、delete;文件名与文件描述符;系统打开文件表和进程打开文件表;目录路径解析。
  3. 第三梯队:必须理解概念差别——逻辑结构和物理结构;树形目录;软链接与硬链接;superblock、inode、vnode;VFS;mount。
  4. 第四梯队:理解即可但不能完全不看——文件保护、ACL、口令、加密;单级/两级目录;文件系统层次结构等。

尤其是混合索引,资料明确追踪到 2010、2015、2018、2022 等年份;而 open、inode、链接和近年来新增的 VFS 也有持续考查记录,所以这几块应该作为第 4 章的复习核心。

如果把这一章进一步压成考场上的四句话,就是:

目录解决“文件叫什么、在哪个 inode”。 inode/FCB 解决“这个文件是什么、数据块在哪里”。 文件物理结构解决“这些数据块怎么组织”。 文件系统解决“所有文件、目录、磁盘空间怎样统一管理”。

On this page

一、本章整体框架二、首先搞懂:文件到底是什么?三、文件的逻辑结构1. 无结构文件:流式文件四、有结构文件1. 顺序文件2. 索引文件3. 索引顺序文件五、★★★★★ 本章最核心:文件的物理结构六、连续分配为什么快?最大问题七、链接分配八、FAT:显式链接FAT 的代价九、★★★★★ 索引分配十、单级索引最大文件长度怎么算?十一、多级索引十二、★★★★★ 混合索引十三、混合索引容量计算——必须会10 个直接地址一个一级间接地址一个二级间接地址一个三级间接地址十四、另一个高频:访问一个数据块要几次磁盘 I/O?直接地址一级间接二级间接三级间接十五、三种物理分配方式最后对比十六、★★★★★ FCB:操作系统怎么知道“这是一个文件”?十七、★★★★★ inode 为什么出现?十八、经典 inode 目录检索计算没有 inode引入 inode这种题的本质十九、目录到底是什么?二十、目录结构的发展单级目录两级目录二十一、树形目录绝对路径相对路径二十二、★★★★★ 文件打开 open:一定要理解全过程二十三、系统打开文件表 vs 进程打开文件表二十四、为什么打开以后不再使用文件名?二十五、close 的过程二十六、create / delete / read / writecreatereadwrite二十七、★★★★★ delete 为什么比想象复杂?二十八、★★★★★ 硬链接二十九、删除一个硬链接会发生什么?三十、★★★★★ 软链接三十一、硬链接和软链接对比三十二、文件保护三十三、ACL三十四、口令保护和加密保护三十五、★★★★★ 文件系统在磁盘中的布局三十六、超级块 superblock三十七、内存中的文件系统结构三十八、★★★★★ 外存空闲空间管理三十九、★★★★★ 位示图四十、位示图行列号计算四十一、成组链接法四十二、成组链接的分配过程四十三、成组链接的回收四十四、★★★★★ VFS:虚拟文件系统四十五、VFS 的四种核心对象四十六、用 write 理解 VFS 全链路四十七、文件系统挂载 mount四十八、本章最容易混淆的几个概念四十九、第 4 章计算题统一方法A. inode / 目录项计算B. 多级索引计算C. 位示图五十、最后给你建立一条“真正理解文件系统”的全过程五十一、考研复习时建议优先掌握什么