概述

     起先所有的FAT文件系统都是为IBM PC机器而设计的,这说明了一个重要的问题:FAT文件系统在磁盘上的数据是用“小端”(Little Endian)结构存储的。我们使用4个8-bit的字节——起始字节为byte[0],结束字节为byte[3]——来存储一个32-bit的FAT项(FAT entry)。然后分别给这32位编号为00-31,从下面的图我们可以清楚地看到这32位是如何排序的。

 

     这对于那些使用“大端”(big-endian)存储结构的机器就显得尤为重要,因为在磁盘存取数据之前,必须先完成Big-Endian到Little-Endian之间的转换。每个FAT文件系统都由4部分组成,这些基本区域按如下顺序排列。

0——保留区(Reserved Region);
1——FAT区(FAT Region);
2——根目录区(Root Directory Region,FAT32卷没有此域);
3——文件和目录数据区(File and Directory 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字节的话最多32MB——2^16×2^9=32MB),这一个限定是由于定义“总扇区数”的变量本身是一个16-bit的数据类型。这一个限制在MS-DOS 3.x中有所改进,它使用一个32bit的变量来存储“总扇区数”(若每个扇区512字节,则每个FAT卷的最大容量为2^32×2^9=2^41=2048GB)。

     在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_开头的项都是启动扇区(boot sector)的一部分,而不是真正属于BPB内容。下面是FAT 0扇区的内容,BPB也包含其中。


字节位移


字段长度


字段名

0x00

3个字节

跳转指令

0x03

8个字节

厂商标志和OS版本号

0x0B

53个字节

BPB

0x40

26个字节

扩展BPB

0x5A

420个字节

引导程序代码

0x01FE

2个字节

有效结束标志

 


名称


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是一种常用的格式。

BS_OEMName
(OEM、OS版本号)

3

8

  建议值为MSWIN4.1,此域经常引起人们的误解,其实这只是一个字符串而已,Microsoft的操作系统似乎并不关心此域。但其他厂商的FAT驱动程序可能会检测到此项,这就是为什么建议将此域设定为“MSWIN4.1” 的原因,这样可以尽量避免兼容性的问题。你可以更改它的内容,但这有可能造成某些FAT驱动程序无法识别该磁盘。在很多情况下,该域用于显示格式化该FAT卷的操作系统的名称。
(厂商标志和OS版本号)

BPB_BytesPersec
(每扇字节数)

11

2

每扇区字节数,取值只能是以下的几种情况:512、1024、2048或者是4096,一般情况下,设置为512将会取得更好的兼容性,目前有很多的FAT代码都是硬性的规定每扇区字节数为512,而不是实际检测该区域的值。Microsoft操作系统能够很好地支持1024、2048和4096各种数值。
NOTE:请不要曲解此处“最好的兼容性”的意思,如果某些存储介质的物体特性决定其值为N,那么你就必须使用该数值N,该数值N一定是小于等于4096。那么取得“最好的兼容性”的办法就是使用该特定的N值。

BPB_SecPerClus
(每簇扇区数)

13

1

每簇扇区数,其值必须是2的整数次方(该整数必须大于等于0),如1、2、4、8、16、32、64或128,同时还必须保证每簇的字节数不超过32K,即——保证(BPB_BytesPersec * BPB_SecPerClus ≤ 32K)(1024×32)该值大于32K是绝对不允许的,虽然有些版本的操作系统支持每簇字节数最大到64K,但很多应用程序的安装程序都无法在这样的FAT文件系统上正常运行。

BPB_RsvdSecCnt
(保留扇区数)

14

2

保留区中保留扇区的数目,保留扇区从FAT卷的第一个扇区开始,此域不能为0,对于FAT12和FAT16必须为1,FAT32的典型取值为32,目前很多FAT程序都是硬性规定FAT12/FAT16的保留扇区为1,而不对此域进行实际的检测,Microsoft的操作系统支持任何非零的值。

BPB_NumFATs
(FAT副本数)

16

1

此卷中FAT表的份数。任何FAT格式此域都建议为2。虽然此域取值为其他≥1的数值也是合法的,但是对于很多FAT程序和部分操作系统来说,此项不为2的时候将无法正常工作。但是当不为2时,Microsoft的操作系统仍然能良好工作。可依然强烈建议此项值为2。
选择此项的标准值为2的原因是为了提供一份FAT表的备份,当其中一个FAT表所在的扇区被损坏时我们可以从备份的FAT表中读出正确的数据。可是对于一些非磁盘介质的存储器(如FLASH卡),这一特性变得毫无用处,如果想使用1个FAT表来节省空间,那么带来的问题将是某些操作系统无法识别该FAT卷。

 

BPB_RootEntCnt
(根目录项数)

17

2

对于FAT12和FAT16,此域中包含根目录中的目录项数(每个项长度为32Kbytes),对于FAT32,此项必须为0。对于FAT12和FAT16,此数值乘以32,必须为BPB_BytesPersec的偶数倍,为了达到更好的兼容性,FAT12/FAT16应该取值为512。

BPB_TotSec16
(总扇区数)

19

2

早期版本中16-bit的总扇区数,这里的总扇区数包括FAT卷上四个基本区的全部扇区,此域可以为0,若此域为0,那么BPB_TotSec32必须非0,对于FAT32,此域必须为0。对于FAT12/FAT16,此域填写总扇区数,如果该数值小于0x10000的话,BPB_TotSec32必须为0。

BPB_Media
(媒体描述符)

21

1

对于“固定”(不可移动)的存储介质而言,0xF8是标准值,对于可以移动的存储介质,经常使用的数值是0xF0,此域合法的取值可以是0xF0,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE和0xFF。另外要提醒的一点是,无论此域写入什么数值,同时也必须在FAT[0]的低字节写入相同的值,这是因为早期的MSDOS 1.x使用该字节来判定是何种存储介质。

BPB_FATSz16
(每FAT扇区数)

22

2

FAT12/FAT16一个FAT表所占的扇区数,对于FAT32来说,此域必须为0,在BPB_FATSz32中有指定其FAT表的大小。

BPB_SecPerTrk
(每磁道扇区数)

24

2

每磁道扇区数,用于BIOS中断0x13,此域只对于有“特殊形状”(由磁头和柱面分割为若干磁道)的存储介质有效,同时必须可以调用BIOS的0x13中断得到此数值。

BPB_NumHeads
(磁头数)

26

2

磁头数,用于BIOS的0x13中断,类似于上面的BPB_SecPerTrk,只有对特殊的介质才有效,此域包含一个至少为1的数值,比如1.4M的软盘,此域为2。

BPB_HiddSec
(隐藏扇区数)

28

4

在此FAT分区之前所隐藏的扇区数,必须使用调用BIOS的0x13中断可以得到这个数值,对于那些没有分区的存储介质,此域必须为0,具体使用什么由操作系统决定。

BPB_TotSec32
(总扇区数)

32

4

该卷总扇区数(32-bit),这里的总扇区数包括FAT卷上四个基本区的全部扇区,此域可以为0,若此域为0,则BPB_TotSec16必须为非0,对于FAT32,此域一定是非0。对于FAT12/FAT16,如果总扇区数大于或等于0x10000(64KB)的话,此域就是总扇区数,同时BPB_