文件分配表(File Allocation Table,FAT)家族起源于小型 Microsoft 系统,后来成为 DOS 和 IBM PC 介质的交换格式。简单的数据结构使 FAT 适用于启动固件和资源受限的操作系统。相同的设计不包含日志记录、所有权和事务语义,因此它至今仍被使用的原因是互操作性,而不是故障隔离。
卷布局 #
FAT 卷由按逻辑扇区计量的区域组成:
- 保留区域以卷引导扇区及其 BIOS 参数块(BPB)开头。FAT32 还可以在此处放置 FSInfo 扇区,并且通常会放置一个备用引导扇区。
- 一个或多个 FAT 副本包含固定宽度的分配项。通常使用两个副本,但实际数量由 BPB 指定。
- 在 FAT12 和 FAT16 中,根目录区域的位置和项数是固定的。
- 数据区域包含编号后的簇。在 FAT32 中,根目录不是固定区域,而是该区域中的普通簇链。
BPB 提供每扇区字节数、每簇扇区数、保留扇区数、FAT 数量、总扇区数和 FAT 大小。读取器根据这些字段推导区域边界,而不是搜索目录签名。必须检查算术运算是否溢出,因为损坏的 BPB 值可能导致读取范围超出卷边界。
簇与 FAT 分类 #
簇是文件系统的分配单位。在 Microsoft 定义的 FAT 格式中,一个簇包含数量为 2 的幂次的扇区。簇编号 0 和 1 为保留编号;数据簇从 2 开始。数据簇数量由 BPB 按以下方式计算:
root_dir_sectors =
ceil(root_entry_count × 32 / bytes_per_sector)
first_data_sector =
reserved_sectors + fat_count × sectors_per_fat + root_dir_sectors
data_clusters =
floor((total_sectors - first_data_sector) / sectors_per_cluster)卷的分类依据是簇数量,而不是标签字符串或分区类型字节:
| 分类 | 数据簇数量 | 项表示 |
|---|---|---|
| FAT12 | 少于 4,085 | 打包的 12 位项 |
| FAT16 | 4,085 至 65,524 | 16 位项 |
| FAT32 | 65,525 或更多 | 32 位项,其中低 28 位有效 |
实际可用的上限还取决于簇大小、实现策略以及 BPB 中的字段。更宽的项可以表示更多簇,但会为每个 FAT 副本消耗更多扇区。
分配项与簇链 #
每个 FAT 项描述对应的簇。其值可以表示:
- 表示空闲簇的零值;
- 表示链中下一个链接的其他簇编号;
- 保留簇或坏簇标记;
- 处于链尾范围内的值。
文件的短目录项存储其首个簇和字节长度。读取文件时从该簇开始,沿 FAT 链接继续读取,直到获得足够的字节或遇到结束标记。最后一个簇可能包含超出逻辑长度的空闲字节。FAT32 中的目录以及所有非根目录都使用相同的簇链机制。
链式分配使文件无需找到一个连续的区段即可增长,但碎片化的链需要额外的 FAT 查找和非顺序 I/O。该表也是一个共享的故障点。循环、超出范围的链接、过早出现的结束标记,或同一个簇被两个文件声明使用,都会使目录元数据与分配状态不一致。
多个 FAT 副本不构成日志。写入操作可能在更新某一个副本、目录项或链的一部分之后失败。修复软件必须在过时的副本和推断出的所有权之间进行选择;两个副本逐字节一致,也不能证明目录项正确。FAT32 的 FSInfo 空闲计数和下一个空闲簇提示也可能过时,因此读取器必须将其视为提示信息。
目录项与时间戳 #
标准目录槽为 32 字节。短文件名项包含一个 8.3 文件名、属性标志、时间戳字段、起始簇和文件大小。FAT32 将起始簇拆分为高位字和低位字。首字节的特殊值表示未使用槽或已删除项,而目录属性用于区分子目录和普通文件。
经典 FAT 时间戳编码的是本地民用时间,而不是 UTC 时刻:
- 修改时间的分辨率为两秒;
- 修改日期和创建日期使用打包的年、月、日字段;
- 创建时间可以包含十分之一秒字段;
- 最后访问时间仅存储日期,不存储当天时间。
时区和夏令时的解释属于实现责任。因此,在不同系统之间复制卷可能会改变显示的时刻,而不改变磁盘上的位。验证时必须拒绝不可能的日期,不能直接将打包值传递给日历 API。
VFAT 长文件名 #
VFAT 通过将长文件名(LFN)项放置在关联短文件名项之前,来保持与 8.3 读取器的兼容性。LFN 槽具有以下特征:
- 使用属性值
0x0F,旧版 FAT 读取器不会将其视为普通文件; - 在不连续的字段中存储最多 13 个 UTF-16 代码单元;
- 携带一个序号,用于表示其位置以及是否为最后一个槽;
- 重复存储由短 8.3 文件名导出的校验和。
槽在磁盘上按序号逆序出现,随后是短文件名项。只有在序号、属性和校验和一致时,读取器才会重构文件名。否则,短文件名仍是安全的身份标识。UTF-16 代码单元可以包含代理对,而 FAT 禁止的字符和尾随空格规则仍属于独立的验证问题。
引导扇区几何信息与分区元数据 #
由于 FAT 是随着 BIOS CHS 引导和分区磁盘发展起来的,BPB 仍保留每磁道扇区数、磁头数、介质描述符和隐藏扇区等字段。现代系统通过 LBA 访问卷,因此几何值可能是合成的。它们描述的是引导时兼容性,而不是物理盘片布局。
卷引导扇区属于 FAT,而 MBR 或 GPT 项位于卷外部,用于定位该卷。分区的起始位置和长度必须与根据 BPB 推导的边界一致,但一种结构不能替代另一种结构。在额外的 UEFI 要求下,UEFI 固件使用 FAT 文件系统作为 EFI System Partition;没有相应的分区元数据和引导路径,任意 FAT 卷都不会成为 EFI System Partition。
运行影响 #
FAT 仍适用于可移动介质、固件可见的卷以及资源受限的设备,因为独立实现可以使用很少的机制对其进行解析。应用程序仍应在移除介质前刷新数据,在读取不可信镜像时验证所有偏移量和簇链长度,并在尝试修复前保留镜像。没有日志,便无法区分已完成的更新和断电留下的中间状态。
评论
在 GitHub 上阅读或评论(发表评论需要登录)