Introduction

先了解一下,不同区域的相对位置以及其在磁盘上的大致位置。

不同区域的相对位置: 不同区域的相对位置

不同区域在磁盘上的大致位置: 从磁盘看不同区域

当然,上图讲的是 FAT16,其 FDT 独立于 DATA。 FAT32 是没有 FDT 的,其根目录项存储在 DATA 区的前端。

隐藏扇区

隐藏扇区(hidden sector)是在分区之前的部分。通常所说的 MBR,它是隐藏扇区的第一个扇区,也是整个存储介质的第一个物理扇区。

保留扇区

保留扇区(reserved sector) 是分区之内, FAT 表之前的所有扇区。通常所说的 DBR,就是保留扇区的第一个逻辑扇区。如果隐藏扇区为 0 个,那么 DBR 所在的扇区就成为了第一个物理扇区,当然,这是不可能的。 注:保留扇区包含 DBR,但不能认为其仅仅是 DBR。例如: 在 FAT32 的保留区中除了 DBR 还有个 FSINFO 信息区,用来记录文件系统空闲簇的数量,下一可用簇的簇号。

Windows 文件系统

20200423111332
20200423111341

FAT 16 的结构划分为:

隐藏扇区 | (保留扇区 | FAT 区 | FDT | 数据区 |)

分区前 <-|->分区之后,也就是文件系统的起始部分(后面这一部分是一个主分区,Windows 上一般只有一个主分区,然后就是扩展分区了)

注: FAT32 单个文件最大 4 GB,也从一个方面体现出它已经跟不上时代的步伐了,当前 Windows 一般都是使用 NTFS 了

FAT

FAT(File Allocation Table)文件系统是 Windows 操作系统所使用的一种文件系统。

FAT 文件系统的发展经历了 FAT12、FAT16 和 FAT32 三个阶段。当然,目前 Windows 主要使用更高级的 NTFS 了。

FAT 表

FAT 表(FAT 文件分配表)可以看作是 DOS 文件管理系统用来记录每个文件的存储位置的表格,FAT 文件系统使用”簇“为数据单元,以链的方式存放簇号,所有簇从 2 号开始编号(NTFS 的簇从 0 号开始)。每个簇在 FAT 表中占有一个登记项,即:FAT 簇登记项。 又因为 FAT 表的前两个登记项是特殊标记,所以从 2 号开始,簇编号对应登记项编号。

FAT 表通过描述文件系统内的簇分配状态,说明文件系统内数据所分配的连续簇的顺序关系(即表明文件或目录的下一簇的序号)。

FAT 表中没有指出哪个是文件的第一个簇,所以必须从目录中提取文件的首地址,然后通过 FAT 来访问剩下的簇。所以,都是先去 FDT(文件目录表)中获得文件的首簇号,然后到 FAT 表中确定文件的簇链。

分配给文件的簇的总字节数必须大于目录记录中文件大小区域指出的文件大小。除非文件的大小是簇的整数倍的话,否则最后一个簇的末尾就会有一部分未使用的空间。文件大小是 0 的文件将不会分配簇,在目录记录中的簇数量应该为 0。

根据 FAT 表中每个登记项所占的位数将 FAT 划分为了 FAT12, FAT16, FAT32。

  1. FAT12

    12 位表项值,可表示 4096 个簇 每簇 64 个扇区(32KB),可表示 262144 个扇区

  2. FAT 16

    16 位表项值,可表示 65 535 个簇 一般每簇不多于 64 个扇区(32KB)。 最多管理 32x65535=2097120KB=2048MB=2GB 4 个分区,即管理 2x4=8GB

  3. FAT32

    32 位表项值,可表示 4294967296 个簇 若每个簇 4KB,理论可管理 4KBx 4294967296 =16TB Windows 2000 以前,簇最大单位为 64 个扇区,之后为 128 个扇区

  • FAT 文件系统中,重要的数据结构为文件分配表和目录项。
  • FAT 在 DOS 引导扇区之后,有两个,基本表和备份。
  • 每个 FAT 所占扇区数通过 BPB 偏移 16H 和 24H 处的值确定

常规规则:

  • 数量:通常情况下一个 FAT 文件系统会有两个 FAT 表, 但有时候也会允许只有一个 FAT 表, FAT 表的具体个数记录在引导扇区的 偏移 0x10 字节处。

  • 位置:因为 FAT 区位于文件系统的保留区之后,所以 FAT1 在文件系统中的位置可以通过引导记录中偏移 0x0E~0x0F 字节处的“保留扇区”数得到。

  • FAT2 紧跟在 FAT1 之后, 它的位置可以通过 FAT1 的位置加上每个 FAT 表的大小扇区数获得。

FAT 表中记录了每个文件的簇链结构;FAT 表中记录的与数据区簇对应的表项,从 0 号标记开始至当前数据区所分配的簇的最大数值,记录簇信息到 FAT 项;但是注意:其中 0 号~1 号簇的值都是操作系统预先不留设定的特殊标记,而数据区的起始簇是 2 号簇。

FAT16

FAT16 结构

20200423124733
20200423122329

FAT16 簇登记项

FAT16 登记项表

不详细介绍。仅以实例来介绍簇链的概念。

FAT16 实例

需要根据 “FAT16 登记项表” 一图中的 16 位表项值那一列来判断。 首先,0 号和 1 号簇是特殊标记,我们不用管。从 2 号簇开始,

  1. 2 号簇: 0xFFFF 表示文件结束,说明该文件只用了这一个簇。
  2. 3 号簇: 0x0004 表示已分配簇,其值为 4,表示该文件并未结束,下一簇是 4 号簇
  3. 4 号簇 同上,说明还是上面一个文件的下一簇在 5 号簇
  4. 5 号簇 同上,同上,说明还是上面一个文件的下一簇在 6 号簇
  5. 6 号簇 0xFFFF,说明文件结束,表示从 3 号簇到 6 号簇,一个文件的簇链结束。
  6. 7 号簇 0xFF 文件结束,代表该文件在本簇号就结束了。

综上,有 3 个文件。

FAT32

FAT32 结构

FAT32

FAT32 不使用固定的根目录区,根目录与其它子目录一样动态分配空间,其首簇号在 BPB 中记录。

FAT32 登记项表

FAT 表由一些列大小相等的表项组成。FAT32 中每个簇的状态,使用 32bit(4 字节)记录在 FAT 表中。

FAT32 表中的所有字节位置以 4 个字节为单位进行划分,并以所有划分后的位置由 0 进行地址编号。“0 号 和 1 号” 地址被系统保留并存储特殊标识内容。

从 2 号地址开始,每个地址对应于数据区的簇号,FAT 表中的簇登记项编号与数据区中的簇号相同。称 FAT 中的这些四字节一组划分的项的地址为 FAT 表项, FAT 表项中记录的值为 FAT 表项值。(簇编号与簇内内容关系 和 Map 中的键-值关系相同)

当文件系统创建时(就是格式化操作时),分配给 FAT 区域的空间将会被清空, 在 FAT1 与 FAT2 的 0 号和 1 号表项写入特定值。由于创建文件系统的同时,也会创建根目录,也就是为根目录分配了一个簇空间,通常为 2 号簇,所以 2 号簇所对应的 “2 号 FAT 表项” 也会被写入一个结束标记。

FAT32 表格式说明:

  • 如果某个簇未被使用,他所对应的 FAT 表项内的 FAT 表项值即用 0 进行填充,表示该 FAT 表项所对应的簇未被分配使用

  • 当某个簇被分配使用时,那么他所对应的 FAT 表项的值为文件的下一个存储文件的簇号。如果该文件结束于该簇,则在它的 FAT 表项中记录的是一个文件结束标记,对于 FAT32 而言,代表文件结束的 FAT 表项值为 0x0FFFFFFF

  • 如果某个簇存在坏扇区,则整个簇会用 FAT 表项值 0x0FFFFFF7 标记为坏簇, 不再使用,这个坏簇标记就记录在它所对应的 FAT 表项中。

  • 由于簇号起始于 2, 所以 FAT 表的 0 号表项与 1 号表项不予任何簇对应。FAT32 的 0 号表项值总是 “F8FFFF0F”

注意: 可以搜索扇区偏移 0 字节处的该值(F8FFF0F)以查找 FAT 表。

  • 1 号表项可能被用于记录“脏标志”, 以说明文件系统没有被正常卸载或者磁盘表面存在错误。 不过此值似乎不重要,正常情况下,1 号表项为:“FFFFFFFF”或“FFFFFF0F”(当然,这里是直接看上去,如果说其值的话,需要按照小端模式读出来,“0xFFFFFFFF”或“0x0FFFFFFF”)
FAT32 实例

那么这个 FAT32 表有几个文件呢? 答案是: 10 个文件. 这里就不详细介绍了,根据 FAT16 的实例和上面 FAT32 的格式说明,应该很容易理解。

计算公式

  1. 已知簇号,如何找到对应的扇区号?

    logic_sector_sn=(kown_cluster_sn-2)*Sector_per_cluster+DATA_begin_sector_sn 逻辑扇区号 = (已知簇号 - 2) * 每簇的扇区数 + DATA 区起始扇区号

    已知簇号 - 2 的是因为要求逻辑扇区号(即: 相对于 DBR 区的扇区号),而 DATA 区默认从 2 簇开始。

  2. FAT 表的入口地址 = 隐藏扇区数 + 保留扇区数

适用于 FAT16:

  1. 根目录区的入口地址 = FAT 表的入口地址 + 所有 FAT 的扇区数
  2. DATA 数据区的入口地址 = 根目录区的入口地址 + 根目录区的扇区数

适用于 FAT32:

  1. DATA 数据区的入口地址 = FAT 表的入口地址 + 所有 FAT 的扇区数
  2. 根目录区(FDT)的入口地址 = DATA 区起始扇区号 + (首簇号 - 2)*每簇的扇区数

习题

  1. 设:簇空间设置为每簇 512B,分区大小为 16GB,即 FAT32 表占多少空间? 最大簇号为 16GB/512B = 16*(2^30)/512 = 33 554 432 FAT32 表项为每个簇占 4 个字节,即 33 554 432 x 4B = 128MB 2 个 FAT32 表,即 2 x 128MB = 256MB
  2. 设:簇空间设置为每簇 4KB,分区大小为 16GB,即 FAT32 表占多少空间? 最大簇号为 16GB/4KB=4 194 304
    FAT32 表项为每个簇占 4 个字节,即 4 194 304 x 4B = 16MB 2 个 FAT32 表,即 2 x 16MB = 36MB
  3. 访问时间效率通过比较文件所占簇的个数来实现

参考资料

  1. FAT32 文件格式示例解析
  2. 数据恢复之 Fat 篇