Microsoft®
Hardware White Paper
Designing Hardware for Microsoft® Operating Systems
Microsoft Extensible Firmware Initiative
FAT32 File System Specification
FAT: General Overview of On-Disk Format
Version 1.03, December 6, 2000
Microsoft Corporation
译注:
刚完成的项目内容涉及 FAT 文件系统,因此在查阅手册的同时把文档翻译了一下,希望能对那些和我
一样初次使用 FAT 的朋友有所帮助。因本人对 FAT 并不十分了解,翻译所做的也只是文字表面工作,出现
各种错误在所难免,因此:本文只适用于初学者作为了解材料,需要获得技术信息的朋友请查阅原版英文
资料!
发现错误的朋友请mail yuwh@amoi.com.cn指正,本人将不胜感激。
Microsoft Extensible Firmware Initiative FAT32 File System Specification
IMPORTANT-READ CAREFULLY:
……
原文长 5 页,大意是告诫人们不要使用 D 版云云,此略。
本文的一些约定
以字符“0x”开头的数字为 16 进制,若开头没有字符“0x”则表明该数字为 10 进制。
本文的程序使用 C 语言书写,书写风格可能与教科书中严格定义的有所出入。
一些变量在程序中没有注明其数据类型是 16-bit 还是 32-bit,因为我们知道你有能力正确地完成这
些数据类型之间的转换,并保证在转换 32-bit 为 16-bit 的过程中不会造成数据丢失。同时请注意,所有
的数据类型均是无符号类型(UNSIGNED),不要尝试使用有符号整形(signed integer types)来进行 FAT
运算,否则一些 FAT 卷将会因此而出错。
概述(适用于所有 FAT 类型)
起先所有的 FAT 文件系统都是为 IBM PC 机器而设计的,这说明了一个重要的问题:FAT 文件系统在磁
盘上的数据是以“小端” (little-endian) 结构存储的。我们使用 4 个 8-bit 的字节 -- 起始字节为
byte[0],结束字节为 byte[3] -- 来存储一个 32-bit 的 FAT 项(FAT entry)。然后分别给这 32 位编号为
00-31,从下表我们可以清楚地看到这 32 位是如何排序的(最低位为 00).
FAT: General Overview of On-Disk Format
byte[3] 3 3 2 2 2 2 2 2
1 0 9 8 7 6 5 4
byte[0] 0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
byte[2] 2 2 2 2 1 1 1 1
3 2 1 0 9 8 7 6
byte[1] 1 1 1 1 1 1 0 0
5 4 3 2 1 0 9 8
这对于那些使用“大端”(big-endian)存储结构的机器就显得尤为重要,因为在磁盘存取数据之前,
必须先完成 big-endian 和 little-endian 之间的转换。
每个 FAT 文件系统由 4 部分组成,这些基本区域按如下顺序排列:
0 – 保留区(Reserved Region)
1 – FAT 区(FAT Region)
2 – 根目录区(Root Directory Region, FAT32 卷没有此域)
3 – 文件和目录数据区(File and Directory Data Region)
启动扇区与 BPB
BPB(BIOS Parameter Block)是 FAT 文件系统中第一个重要的数据结构,它位于该 FAT 卷的第一个扇区,
同时也属于 FAT 文件系统基本区域的保留区。这个扇区又叫做“启动扇区”、“保留扇区”、“0 扇区”,众多
的叫法都说明一个相同的问题:该扇区是 FAT 卷的第一个扇区。
这是 FAT 文件系统中第一个让人感到迷惑的地方,对于 MS-DOS 1.x 的版本,启动扇区中并没有 BPB 这
么一个东西,FAT 文件系统的最早期版本只有两种不同的格式:使用于单面或双面的 360K 5 寸软盘。这两
种格式是通过 FAT 的第一个字节(FAT[0]的低 8 位)来区分的。
在 MS-DOS 2.x 以后,启动扇区里增加了 BPB 用于区分磁盘介质,同时不再支持老的磁盘介质区分方式
(用 FAT 的第一个字节来区分),所有的 FAT 文件系统卷必须在启动扇区中包含 BPB。
这又是一个迷惑人的地方,BPB 具体是什么样的?在 MS-DOS 2.x 的定义中,每个 FAT 卷的扇区数不能
多于 65536(每个扇区 512 字节的话最多 32M),这一限定是由于定义“总扇区数”的变量本身是一个 16-bit
的数据类型。这一个限制在 MS-DOS 3.x 中有所改进,它使用一个 32-bit 的变量来存储“总扇区数”。
在 Win95 操作系统,确切的说应该是在 OSR2(OEM Service Release 2)出现的时候 BPB 的内容有了
新的变化,在这一版本中引入了新的 FAT 类型 —— FAT32。在 FAT16 中,由于 FAT 表的大小限制了有效的
簇数(cluster),同时也就限制了磁盘空间的大小,如果每个扇区为 512 字节的话,那么 FAT16 格式只能
支持到 2G。FAT32 的引入改变了这一状况,不再需要增加分区来管理大于 2G 的硬盘。
FAT32 的 BPB 内容和 FAT12/FAT16 的内容在 BPB_ToSet32 区域以前完全一致,而从偏移量 36 开始他们
的内容有所区别,具体内容要看 FAT 类型为 FAT12/FAT16 还是 FAT32(后面的内容会提到如何区分 FAT 格式)
这点保证了在启动扇区中包含一个完整的 FAT12/FAT16 或 FAT32 的 BPB 内容,这么做是为了达到最好的兼
容性,同时也为了保证所有的 FAT 文件系统驱动程序能正确地识别和驱动不同 FAT 格式,并让他们良好地
工作,因为他们包含了现有的全部内容。
NOTE: 在以下的描述中,凡名称与 BPB_开头的域都是 BPB 的一部分,凡名称与 BS_开头的项都是启动
第 2 页
扇区(boot sector)的一部分,而不是真正属于 BPB 内容。下面是 FAT 0 扇区的内容,BPB 也包含其中。
FAT: General Overview of On-Disk Format
启动扇区与 BPB 结构
名称
Offset
(byte)
大小
(byte)
BS_jmpBoot
0
3
描述
跳转指令。指向启动代码,允许以下两种形式:
jmpBoot[0] = 0xEB, jmpBoot[1] = 0x??, jmpBoot[2] = 0x90
和
jmpBoot[0] = 0xE9, jmpBoot[1] = 0x??, jmpBoot[2] = 0x??
0x??表示该字节可以为任意 8-bit 值,这是 Intel x86 架构 3
字节的无条件转移指令,跳转到操作系统的启动代码,这些
启动代码往往紧接 BPB 后面 0 扇区里的剩余字节,当然也
可能位于其他扇区。以上的两种形式任取。jmpBoot[0] =
0xEB 是较常用的一种格式
建议值为“MSWIN4.1” 此域经常引起人们的误解,其实这
只是一个字符串而已,Microsoft 的操作系统似乎并不关心
此域。但其他厂商的 FAT 驱动程序可能会检测此项,这就是
BS_OEMName
3
8
为什么建议将此域设为 “MSWIN4.1”的原因,这样可以尽
量避免兼容性的问题。你可以更改它的内容,但这有可能造
成某些 FAT 驱动程序无法识别该磁盘。很多情况下该域用于
显示格式化该 FAT 卷的操作系统的名称。
每扇区字节数,取值只能是以下的几种情况:512、1024、
2048 或是 4096,设置为 512 将取得最好的兼容性,目前有
很多的 FAT 代码都是硬性的规定每扇区字节数为 512,而不
是实际检测该此域的值,Microsoft 的操作系统能够很好地
BPB_BytsPerSec
11
2
支持 1024、2048 和 4096 各种数值。
NOTE: 请勿曲解此处“最好的兼容性”的意思,如果某些存
储介质的物体特性决定其值为 N,那么你就必须使用该数值
N,该 N 值一定是小于或是等于 4096。那么取得“最好的兼
容性”的办法就是使用该特定的 N 值。
每簇扇区数,其值必须是 2 的整数次方(该整数必须>=0),
如 1、2、4、8、16、32、64 或 128,同时还必须保证每簇
的 字 节 数 不 超 过 32K , 既 : 保 证
BPB_SecPerClus
13
1
(BPB_BytsPerSec * BPB_SecPerClus <= 32K (1024*32)
BPB_RsvdSecCnt
BPB_NumFATs
14
16
2
1
该值大于 32K 是绝对不允许的,虽然有些版本的操作系统支
持每簇字节数最大到 64K,但很多应用程序的安装程序都无
法在这样的 FAT 文件系统上正常运行。
保留区中保留扇区的数目,保留扇区从 FAT 卷的第一个扇区
开始,此域不能为 0,对于 FAT12 和 FAT16 必须为 1,FAT32
的 典 型 取 值 为 32, 目 前 很 多 FAT 程 序 都 是 硬 性 规 定
FAT12/FAT16 的保留扇区数为 1,而不对此域进行实际的检
测,Microsoft 的操作系统支持任何非零的值.
此卷中 FAT 表的份数。任何 FAT 格式此域都建议为2。虽
然此域取值为其他>=1 的数值也是合法的,但是很多 FAT
程序和部分操作系统对于此项不为2的时候将无法正常工
第 3 页
FAT: General Overview of On-Disk Format
作。当不为2时,Microsoft 的操作系统仍能良好的工作。
但仍然强烈建议此域为2。
选择此项的标准值为2的原因是为了提供一份 FAT 表的备
份,当其中一个 FAT 表所在的扇区被损坏时我们可以从备
份的 FAT 表中读取正确的数据。但是对于一些非磁盘介质
的存储器(如 FLASH 卡),这一特性变得毫无用处,如果想
使用 1 个 FAT 表来节省空间,那么带来的问题将是某些操
作系统无法识别该 FAT 卷。
对于 FAT12 和 FAT16 此域包含根目录中的目录项数(每个
项长度为 32 bytes),对于 FAT32,此项必须为 0。对于 FAT12
和 FAT16,此数值乘以 32 必须为 BPB_BytsPerSec 的偶数倍,
为了达到最好的兼容性,FAT12/FAT16 应该取值为 512.
早期版本中 16-bit 的总扇区数,这里的总扇区数包括 FAT
卷上四个基本区的全部扇区,此域可以为 0,若此域为 0,
BPB_RootEntCnt
17
2
BPB_TotSec16
19
2
那么 BPB_TotSec32 必须非 0,对于 FAT32,此域必须为 0。
对于 FAT12/FAT16,此域填写总扇区数, 如果该数值小于
0x10000 的话,BPB_TotSec32 必须为 0。
对于“固定”(不可移动)存储介质而言,0xF8 是标准值,
对于可移动存储介质,经常使用的数值是 0xF0,此域合法的
取值可以取 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD,
0xFE 和 0xFF。另外要提醒的一点是,无论此域写入什么数
值,同时也必须在 FAT[0]的低字节写入相同的值,这是因
为早期的 MSDOS 1.x 使用该字节来判定是何种存储介质。
FAT12/FAT16 一个 FAT 表所占的扇区数,对于 FAT32 此域必
须为零,在 BPB_FATSz32 中有指定其 FAT 表的大小
每磁道扇区数,用于 BIOS 中断 0x13,此域只对于有“特殊
形状”(由磁头和柱面分割为若干磁道)的存储介质有效,
同时必须可以调用 BIOS 的 0x13 中断得到此数值
磁 头 数 , 用 于 BIOS 的 0x13 中 断 , 类 似 于 上 面 的
BPB_SecPerTrk,只有对特殊的介质才有效,此域包含一个至
少为 1 的数值,比如 1.4M 的软盘此域为 2
在此 FAT 分区之前所隐藏的扇区数,必须使得调用 BIOS 的
0x13 中断可以得到此数值,对于那些没有分区的存储介质,
此域必须为 0,具体使用什么值由操作系统决定。
该卷总扇区数(32-bit),这里的总扇区数包括 FAT 卷上四
个 基 本 区 的 全 部 扇 区 , 此 域 可 以 为 0, 若 此 域 为 0 ,
BPB_TotSec16 必须为非 0,对于 FAT32,此域一定是非 0。对
于 FAT12/FAT16,如果总扇区数大于或等于 0x10000 的话,
此域就是总扇区数,同时 BPB_TotSec16 的值为 0
1
2
2
2
4
4
21
22
24
26
28
32
BPB_Media
BPB_FATSz16
BPB_SecPerTrk
BPB_NumHeads
BPB_HiddSec
BPB_TotSec32
从 Offset 36 开始 FAT12/FAT16 的内容开始区别于 FAT32,现在分两个表格列出,下表为 FAT12/FAT16
的内容:
第 4 页
名称
BS_drvNum
BS_Reserved1 (壹)
BS_BootSig
BS_VolID
Offset
(byte)
大小
(byte)
36
37
38
39
1
1
1
4
BS_VolLab
43
11
BS_FilSysType
54
8
下表为 FAT32 的内容:
名称
Offset
(byte)
大小
(byte)
BPB_FATSz32
36
4
BPB_ExtFlags
40
2
FAT: General Overview of On-Disk Format
描述
用于 BIOS 中断 0x13 得到磁盘驱动器参数,(0x00 为软盘,
0x80 为硬盘)。
NOTE:此域的值实际上由操作系统来决定
保留(供 NT 使用),格式化 FAT 卷时必须把此域设置为 0
扩展引导标记(0x29),用于指明此后的 3 个域可用
卷标序列号,此域以 BS_VolLab 一起可以用来检测磁盘是否
正确,FAT 文件系统可以用此判断连接的可移动磁盘是否正
确,此域往往是由时间和日期组成的一个 32 位值。
磁盘卷标,此域必须与根目录中 11 字节长的卷标一致。
NOTE: FAT 文件系统必须保证在根目录的卷标文件更改或
是创建的同时,此域的内容能得到及时的更新,当 FAT 卷没
有卷标时,此域的内容为“NO NANM ”
以下的几种之一:“ FAT12 ”、“FAT16 ”、“FAT32 ”.
NOTE: 不少人错误的认为 FAT 文件系统的类型由此域来
确定,仔细点你就能发现此域并不是 BPB 的一部分,只是一
个字符串而已,Microsoft 的操作系统并不使用此域来确定
FAT 文件的类型,因为它常常被写错或是根本就不存在,后
面将讨论如何来检测一个 FAT 文件系统的类型,但不管如
何,建议您在此域填写正确的信息,因为一些非 Microsoft
的操作系统会检测此域。
描述
一个 FAT 表所占的扇区数,此域为 FAT32 特有,同时
BPB_FATSz16 必须为 0。
此域 FAT32 特有。
Bits 0-3:不小于 0 的活动 FAT(active FAT)数目,只有
在镜像(mirroring)禁止时才有效。
Bits 4-6: 保留。
Bits 7: -- 0 表示 FAT 实时镜像到所有的 FAT 表中。
-- 1 表示只有一个活动的 FAT 表,这个表就是
bits 0-3 所指定的那个。
Bits 8-15: 保留
此域 FAT32 特有。高位为 FAT32 的主版本号,底位为次版本
号,这个版本号是为了以后更高级 FAT 版本考虑,假设当前
BPB_FSVer
42
2
的操作系统所能支持的 FAT32 版本号为 0:0。那么该操作系
BPB_RootClus
44
4
统检测到此域不为 0 时,它便会忽略这个 FAT 卷,因为它的
版本号比系统能支持的版本要高。
此域 FAT32 特有。根目录所在第一个簇的簇号,通常该数值
为 2,但不是必须为 2。
NOTE: 磁盘工具在改变根目录的位置时,必须想办法让磁
盘上第一个非坏簇作为根目录的第一个簇(比如第 2 簇,除
第 5 页
FAT: General Overview of On-Disk Format
非它已经被标记为坏簇),这样的话,如果此域正好为 0 的
话磁盘检测工具也能轻松的找到根目录所在簇的位置。
此域 FAT32 特有。保留区中 FAT32 卷 FSINFO 结构所占的扇
区数,通常为 1。
NOTE: 在 Backup Boot 中会有一个 FSINFO 的备份,但该备
份只是更新其中的指针,也就是说无论是主引导记录还是备
份引导记录都是指向同一个 FSINFO 结构
此域 FAT32 特有。如果不为 0,表示在保留区中引导记录的
备份数据所占的扇区数,通常为 6。同时不建议使用 6 以外
的其他数值。
此域 FAT32 特有。用于以后 FAT 的扩展使用,对于 FAT32,
此域用 0 填充。
与 FAT12/FAT16 的定义相同,只不过两者位于启动扇区不同
位置而已。
与 FAT12/FAT16 的定义相同,只不过两者位于启动扇区不同
位置而已。
与 FAT12/FAT16 的定义相同,只不过两者位于启动扇区不同
位置而已。
与 FAT12/FAT16 的定义相同,只不过两者位于启动扇区不同
位置而已。
与 FAT12/FAT16 的定义相同,只不过两者位于启动扇区不同
位置而已。
通常设置为“FAT32 ”,请参照 FAT12/FAT16 部分关于此
域的陈述,该域的内容和 FAT 类型的判定无关。
2
2
12
1
1
1
4
11
8
BPB_FSInfo
BPB_BkBootSec
BPB_Reserved
BS_DrvNum
BS_Reserved1
BS_BootSig
BS_VolID
BS_FilSysType
BS_FilSysType
48
50
52
64
65
66
67
71
82
关于 FAT 启动扇区还有一点重要的说明:我们假设里面的内容是按字节排序的,那么扇区[510]的内容
一定是 0x55,扇区[511]的内容一定是 0xAA。
NOTE: 很多 FAT 的资料文档会错误地把 0xAA55 说成是“启动扇区最后两字节的内容”,这样的陈述是
正确的如果 -- 仅仅是如果 -- BPB_BytsPerSec 的值为 512 的话。若是 BPB_BytsPerSec 的值大于 512,
该标记的位置并没有变(虽然在启动扇区的最后两个字节写上 0xAA55 完全没有问题)。
关于 BPB_TotSec16/32 这里再作一点补充:假设现在我们有一块磁盘或一个分区,它的扇区数为 DskSz,
如果 BPB_aTotSec(BPB_TotSec16 或是 BPB_TotSec32 其中不为 0 的那个)的值小于或等于DskSz 并不会使
该 FAT 卷在使用中出现什么错误,实际上,BPB_TotSec16/32 的值不要比 DskSz 小得离谱就不会有什么错
误。
这 样 做 将 造 成 磁 盘 空 间 的 浪 费 , 程 序 本 身 并 不 会 认 为 该 FAT 卷 存 在 什 么 错 误 。 但 是 , 如 果
BPB_TotSec16/32 的值比 DskSz 大的话将会使 FAT 卷遭到严重的损坏,因为它超出了存储介质或是磁盘分
区的边界。当 BPB_TotSec16/32 的值比 DskSz 大时,一些数据将不幸地被丢失。
FAT 数据结构(FAT Data Structure)
接下来一个重要的数据结构就是 FAT 表(File Allocation Table) ,它是一一对应于数据区簇号的列
表。
文件系统分配磁盘空间按簇来分配的。因此,文件占用磁盘空间时,基本单位不是字节而是簇,即使
某个文件只有一个字节,操作系统也会给他分配一个最小单元——即一个簇。为了可以将磁盘空间有序地
分 配 给 相 应 的 文 件 , 而 读 取 文 件 的 时 候 又 可 以 从 相 应 的 地 址 读 出 文 件 , 我 们 把 数 据 区 空 间 分 成
第 6 页
FAT: General Overview of On-Disk Format
BPB_BytsPerSec * BPB_SecPerClus 字节长的簇来管理, FAT 表项的大小与 FAT 类型有关,FAT12 的 表项
为 12-bit,FAT16 为 16-bit,而 FAT32 则为 32-bit。对于大文件,需要分配多个簇。同一个文件的数据并
不一定完整地存放在磁盘中一个连续的区域内,而往往会分成若干段,像链子一样存放。这种存储方式称
为文件的链式存储。为了实现文件的链式存储,文件系统必须准确地记录哪些簇已经被文件占用,还必须
为每个已经占用的簇指明存储后继内容的下一个簇的簇号,对文件的最后一簇,则要指明本簇无后继簇。
这些都是由 FAT 表来保存的,FAT 表的对应表项中记录着它所代表的簇的有关信息:诸如是否空,是否是
坏簇,是否已经是某个文件的尾簇等。
以 FAT16 为例说明 FAT 区的结构如下:
表项
示例代码
描述
0
1
2
3
……
N
N+1
……
FFF8
FFFF
0003
0004
……
FFFF
0000
……
磁盘标识字,必须为 FFF8
第一簇已经被占用
0000h : 可用簇
0002h – FFFEFh: 已用簇,表项中存放文件下
个簇的簇号
FFFF0h - FFF6h : 保留簇
FFF7h : 坏簇
FFF8h – FFFFh : 文件的最后一簇
FAT 的项数与硬盘上的总簇数相关(因为每一个项要代表一个簇,簇越多当然需要的 FAT 表项越多),
每一项占用的字节数也与总簇数有关(因为其中需要存放簇号,簇号越大当然每项占用的字节数就大)
这里说一下 FAT 目录,其实它和普通的文件并没有什么不一样的地方,只是多了一个表示它是目录的
属性(attrib),另外就是目录所链接的内容是一个 32 字节的目录项(32-byte FAT directory entries
后面有具体讨论)。除此之外,目录和文件没什么区别。FAT 表是根据簇数和文件对应的。第一个存放数据
的簇是簇 2。
簇 2 的第一个扇区(磁盘的数据区)根据 BPB 来计算,首先我们计算根目录所占的扇区数:
RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;
因为 FAT32 的 BPB_RootEntCnt 为 0, 所以对于 FAT32 卷 RootDirSectors 的值也一定是 0。上式中的
32 是每个目录项所占的字节数。计算结果四舍五入。
数据区的起始地址,簇 2 的第一个扇区由下面公式计算:
If(BPB_FATSz16 != 0)
FATSz = BPB_FATSz16;
Else
FATSz = BPB_FATSz32;
FirstDataSector = BPB_RsvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors;
NOTE: 扇区号指的是针对卷中包含 BPB 的第一个扇区的偏移量(包含 BPB 的第一个扇区是扇区 0),
并不是必须直接和磁盘的扇区相对应。因为卷的扇区 0 并不一定就是磁盘的扇区 0。
给一个合法的簇号 N,该簇的第一个扇区号(针对 FAT 卷扇区 0 的偏移量)由下式计算:
FirstSectorofCluster = ((N – 2) * BPB_SecPerClust) + FirstDataSector;
NOTE: 因为 BPB_SecPerClus 总是 2 的整数次方(1,2,4,8,……)这意味这 BPB_SecPerClus 的
乘除法运算可以通过移位(SHIFT)来进行。在当前 Intel x86 架构 2 进制的机器上乘法(MULT)和除法
(DIV)的机器指令非常的繁杂和庞大,而使用移位来运算则会相对的快许多。
第 7 页
FAT: General Overview of On-Disk Format
FAT 类型辨别(FAT Type Determination)
这是一个经常产生错误的地方,并且常常会出现诸如 “off by 1”, “off by 2”, “off by 10”
和 “massively off”的错误,事实上,FAT 类型的检测非常简单,FAT 的类型 ——FAT12,或是 FAT16 或
是 FAT32 —— 只能通过 FAT 卷中簇的数量来判定,没有其他办法。
请仔细阅读本段的每一个细节,每个词都很关键。比如“簇数(count of cluster)”并不是指“最大
可取得的簇的数量(maximum valid cluster number)”,因为数据区的第一个簇是簇 2 而不是 0 或 1。
首先我们讨论这个“簇数”是如何计算的,它完全根据 BPB 的内容来确定,我们先计算根目录所占的
扇区数(前面已经有叙述)。
RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;
FAT32 的 RootDirSectors 为 0。
接下来我们检测数据区中扇区数:
If (BPB_FATSz16 != 0)
FATSz = BPB_FATSz16;
Else
FATSz = BPB_FATSz32;
If (BPB_TotSec16 != 0)
TotSec = BPB_TotSec16;
Else
TotSec = BPB_TotSec32;
DataSec = TotSec – (BPB_RsvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors);
计算簇数:
CountofClusters = DataSec / BPB_SecPerClus;
请记住计算结果四舍五入。
现在我们就可以判定 FAT 的类型了,这部分请仔细阅读,否则会导致 off-by-one的错误
在下面的程序中, “<”和 “<=”是不一样的,另外请注意数字不要弄错。
If (CountofCluster < 4085) {
/* FAT 类型是 FAT12 */
}
Else if (CountofCluster < 65525) {
/* FAT 类型是 FAT16 */
}
Else {
/* FAT 类型是 FAT32*/
}
这是检测 FAT 类型的唯一办法。世上不存在簇数大于 4084 的 FAT12 卷,也不存在簇数小于 4085 或是
大于 65524 的 FAT16 卷,同样没有哪个 FAT32 卷的簇数小于 65525。如果你坚持要违背这个规则来创建一
个 FAT 卷那么 Microsoft 的操作系统将无法对此卷进行操作,因为它不认为这是 FAT 文件系统。
NOTE: 如前面所说,目前有很多 FAT 的代码有一些错误,常常会出现 off by 1,2,8,10 或是 off
by 16 的错误 。因此,为和现存的所有代码取得最好的兼容性,强烈建议在格式化 FAT 文件系统时,尽量
使簇数的取值不要接近 4085 或 65525,最好能和这分割点的值相差 16 或更多。
同时请注意这里的簇数(Count of Cluster)是指数据区所占簇的数量(the count of data clusters)
从簇 2 开始算起,而“最大可用的簇数”(Maximum valid cluster number for the volume)是簇数 + 1,
“包括保留簇的簇数”(count of cluster including the two reserved cluster)则为 簇数 + 2。
第 8 页