1.6 我是一块硬盘
把文件名、元数据、数据块、空闲空间和持久化顺序放进同一个文件系统读写合同。
学习目标
- 能沿文件名、元数据、数据块和设备传输追踪一次文件读写
- 能解释文件系统如何分配空闲块、处理边界并保持数据与元数据的持久化顺序
- 能用正常、边界和单一故障样本定位断电、空间不足、路径错误和旧内容问题
1.6 我是一块硬盘
本页依据刘欣《码农翻身》(2018 年第 1 版)及出版社公开书目信息,独立重构 1.6 我是一块硬盘。正文、代码、图示、实验和练习都是本课程重新设计的教学材料,不复制原书正文、插图、练习答案或代码。
硬盘不是“文件躺在连续位置上”的透明盒子。文件系统把名称解析为元数据和数据块,用空闲空间结构分配块,再把读写请求交给块设备;设备只负责持久化块,不能替文件系统决定名称、权限、目录一致性或断电恢复。
三个会让文件系统模型失真的陷阱
五个词组成文件读写合同
<Term def="把路径中的目录项、名称和权限逐级解析为一个文件对象身份的过程。">名称解析</Term>决定请求指向哪个对象。路径解析失败时不能继续读取旧缓存冒充成功。
<Term def="描述文件类型、大小、权限、所有者、时间、块映射和一致性状态的记录。">元数据</Term>不是文件内容的附属装饰,它决定如何解释和保护数据块。
<Term def="保存文件内容的固定大小设备区域,逻辑块到物理块的映射由文件系统维护。">数据块</Term>可能不连续,也可能需要间接映射。设备只看到块请求,不知道文件名。
<Term def="记录哪些块可分配、已分配给谁以及释放是否完成的结构和不变量。">空闲块账本</Term>保证分配不重叠、释放可重用、崩溃后能恢复。容量数字不能替代账本。
<Term def="数据、元数据、目录项和空闲结构按约定被设备稳定保存,并能在断电后恢复到可解释状态。">持久化顺序</Term>决定恢复看到的是旧版本、新版本还是拒绝状态。
五个词组成磁盘链:名称解析找到对象,元数据找到逻辑范围,数据块承载内容,空闲块账本管理空间,持久化顺序让这些记录在断电后仍然一致。
目录节点到机制证据
内部结构
内部结构包括目录项、元数据、数据块映射、空闲块结构和恢复日志。读写一个文件时,必须说明这些结构如何交接,而不是把文件系统当作一个无状态函数。
文件
文件是名称、元数据和内容块的组合对象。大小变化、权限变化和删除都会改变不同结构;“内容读到了”不能证明文件对象的所有状态都一致。
文件的存放
文件的存放可能跨越多个逻辑块和物理块。复核要区分逻辑偏移、块大小、寻址映射和设备队列,尤其要检查扩展与碎片边界。
管理空闲块
管理空闲块需要维护分配、释放、崩溃恢复和所有权不变量。空间不足不是只有“没有容量”一种失败,也可能是账本损坏、碎片或元数据无法安全更新。
文件系统
文件系统把名称、权限、元数据、数据块和空闲结构组织成可访问对象,并向块设备发出读写请求。它还要决定缓存、日志、同步和恢复策略。
文件读写合同
type FileWrite = {
path: string;
metadataBefore: string;
dataBlocks: string[];
freeBlockJournal: string[];
persistenceOrder: string[];
firstDeviation: string;
recovery: string;
decision: "commit" | "replay" | "reject";
};
function canCommit(write: FileWrite) {
return (
write.path.length > 0 &&
write.metadataBefore.length > 0 &&
write.dataBlocks.length > 0 &&
write.freeBlockJournal.length > 0 &&
write.persistenceOrder.length >= 2 &&
write.firstDeviation.length > 0
);
}合同要求写入者能解释路径、元数据、数据块、空闲账本和持久化顺序。不能证明某一步稳定保存时选择 replay 或 reject,而不是用目录项存在掩盖内容和空间状态的不一致。
四步复核一次文件写入
1. 解析名称并读取元数据
冻结路径、权限、文件版本和目录状态,记录每一级名称解析、元数据和逻辑范围。路径不存在、权限不足或对象类型不符时应在这里停止。
Interactive lab
选择持久化样本,定位首个不一致
输入
断电发生在数据块与目录项更新之间,恢复状态依赖日志。
首个变化
持久化顺序先变得不确定,不能只看目录项。
裁决动作
冻结写入,按日志回放并验证旧版本。
先保存结构和顺序,再决定提交、回放或拒绝;目录和容量数字都不是完整证据。
正常、边界与单一故障证据
| 样本 | 只改变的变量 | 预期判定 | 必存证据 |
|---|---|---|---|
| 正常 | 路径、元数据、数据块、空闲账本和同步完整 | 读取与恢复结果可解释 | 映射、顺序、内容、账本 |
| 边界 | 空间、文件大小、权限或断电时点越过阈值 | 停止或恢复到已知版本,不假装成功 | 阈值、旧状态、恢复决策 |
| 单一故障 | 一个目录项、数据块、空闲记录或设备传输失效 | 首个不一致暴露并修复或拒绝 | 首差、所有者、回放日志 |
最小磁盘证据包与反例
证据包包含路径和目录快照、文件元数据、逻辑到物理块映射、空闲块账本、设备请求、缓存和同步点、断电时点、恢复结果、版本和独立复核记录。最终读到内容或目录项存在,只能辅助定位,不能单独证明持久化一致。
反例可以是文件名存在但数据块未写完,也可以是两个文件在恢复后共享了不应共享的块。发现反例后,保留断电前后结构,修复日志或更新顺序,重建空闲账本并重放;不要删除旧块记录来制造干净结果。
术语表
名词解释
本章出现的专业名词,用大白话再讲一遍。
- 名称解析
把路径中的目录项、名称和权限逐级解析为文件对象身份的过程。
- 元数据
描述文件类型、大小、权限、所有者、时间、块映射和一致性状态的记录。
- 数据块
保存文件内容的固定大小设备区域,逻辑块到物理块的映射由文件系统维护。
- 空闲块账本
记录哪些块可分配、已分配给谁以及释放是否完成的结构和不变量。
- 持久化顺序
数据、元数据、目录项和空闲结构按约定被设备稳定保存的顺序。
练习
练习
问题 1: 断电后目录里有新文件名,但读取内容得到旧数据。你先比较哪些证据?
问题 2: 磁盘容量还有余量,但创建大文件失败。如何区分容量、碎片和空闲账本问题?
问题 3: 两个文件恢复后内容互相污染,你会如何回退?
本页小结
1.6 我是一块硬盘的关键不是把硬盘想成连续字节,而是能沿名称解析、元数据、数据块、空闲块和持久化顺序追踪一次读写。面对断电、空间边界和块冲突,保留首个不一致、恢复路径和所有权证据,才能判断是重放、修复还是拒绝。