概述
起先所有的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个字节 |
有效结束标志 |
|
|
|
|
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 |
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 |
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 |
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_ |