磁盘分配方式这块,我在不同阶段理解完全不一样。读书时以为是“记住连续分配有外部碎片、链式分配随机访问慢”这种选择题考点,后来做存储和运维,被一些诡异问题折磨过,才明白分配方式直接决定文件系统的性格:顺序读取快不快、能不能随机访问、能不能扩文件、会不会越用越碎、为什么 U 盘老是提示“文件过大无法存入”。今天这篇就把连续分配和链式分配掰开揉碎,讲清楚实现细节、优劣边界,以及它们在现代文件系统里的影子。
这篇文章适合正在复习操作系统的人、准备面试的开发,也适合被 FAT32 4GB 限制逼疯的普通用户。我把原理、计算、实测命令和踩坑经验一次性说透,不需要你是内核专家,只要跟着思路走,就能把这块内容真正串起来。
1. 连续分配:把文件写成一片连续的地址
1.1 连续分配的基本结构:FCB 里只存两个数字
连续分配的思路特别直白:一个文件在磁盘上占用一组连续的物理块。文件系统在文件控制块中记录两个关键字段,起始物理块号和文件占用的块数。比如文件 A 占用了第 100 到第 156 块,那 FCB 里就记 {起始块=100, 块数=57}。
就这么简单。读取文件第 k 块时,直接拿 起始块号 + k 换算成物理地址去读,不需要查任何映射表,数学上一步到位。系统要定位文件中间的任意一块,时间复杂度是 O(1),这是连续分配最亮眼的优势之一。
写代码模拟时,文件描述符里只需要两个整数。对比后面要讲的链式分配,连续分配在元数据开销上几乎可以忽略不计。1MB 的文件,按 4KB 一块算,共 256 个块,FCB 里存起始块和块数就够了,真正意义上的轻量级管理。
1.2 为什么连续分配的顺序读取“快得离谱”
顺序读一个连续分配的文件时,磁盘的磁头只需要一次性移动到文件起始位置,然后一路读取所有块,不需要反复寻道。机械硬盘时代,寻道和旋转延迟是最大的性能杀手,一次随机寻道可能花费 5 到 10 毫秒,连续读一个块可能只需要几十微秒,两者差两个数量级。所以连续分配的顺序读取速度,是按整个存储物理介质带宽的上限在跑。
具体说,你要顺序读完一个 256 块的文件,连续分配只需要一次寻道,后续全部变成顺序读。而如果文件被拆成 256 个不连续的碎片,最坏情况下每读一块都要重新寻道,时间直接多出几个量级。这也是为什么归档类系统、只读文件系统特别喜欢连续分配,顺序访问就是它们的生命线。
1.3 连续分配的两个致命伤:外部碎片和文件扩展
连续分配最大的问题,外部碎片。文件在磁盘上必须找一块连续的空白区域,频繁创建、删除文件会让磁盘的空闲空间被切成很多细小的区间。比如你删掉了一批小文件,每个文件空出几个块,但这些空闲块分散在磁盘各处,彼此不连接。这时即使所有碎片加起来的剩余空间非常大,也未必能容纳一个需要几十个连续块的大文件。
另一个问题是文件扩展困难。文件创建时系统就要知道它最终有多大,然后分配一整段空间。用户写文件时往往不知道最终大小,如果文件内容超过原分配区间,而区间后面已被别的文件占据,那就没法直接追加。传统做法是找到一块更大的连续空间,把整个文件复制过去,再释放旧空间,成本高到离谱。所以连续分配非常不适合“动态增长型”文件,比如日志、下载中的临时文件。
1.4 补偿手段:紧致操作与只读场景
为缓解外部碎片,系统可以在空闲空间不足但总容量够时执行“紧致操作”,把磁盘上所有已分配文件整体搬移,让所有空闲块连成一片。听起来简单,实际代价极大:文件搬迁期间 I/O 全部停顿,磁盘越满需要搬迁的数据越多,几 GB 甚至几 TB 的数据来回读写,在机械盘上可能耗时几十分钟甚至更久。现代文件系统不会轻易做这种全盘搬迁,最多在特定分区上做碎片整理。
连续分配真正活得滋润的场景是只读、一次性写入的媒介。ISO9660 光盘文件系统就是典型,光盘制作时一次写入,后续不会修改,也没有碎片问题。老式磁带归档也是顺序写顺序读,连续分配天然匹配。另外很多嵌入式系统里的只读文件系统,以及日志文件的只追加模式,也会借用连续分配的思路。把这些场景放在一起看,你会发现连续分配并没有被淘汰,而是退出了“通用型文件系统”的舞台,转而在特定约束下发光发热。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 链式分配:用指针把碎片串起来
2.1 链式分配的原始形态:每个块末尾藏一个指针
链式分配的思路是放弃“连续”这个约束,文件可以占据任意空闲块,每个磁盘块的末尾留出一个指针字段,存放下一个块的块号。FCB 里只需要记录文件的首块号,最多再记录一个尾块号方便追加。
这样做的好处非常明显:文件创建时
