DBR及保留扇区
|
FAT1
|
FAT2
|
数据区
|
EB 58 90 共3个字节,跳转指令本身占用2字节,它将程序执行流程跳转到引导程序处。例如,当前DBR中的“EB 58”,就是代表汇编语言中的“JMP 58”。需要注意该指令本身占用2个字节,计算跳转目标地址时该指令的下一个字节为基准,所以实际上执行的下一条指令应该位于 5A。紧接着跳转是一条空的指令NOP(90H)
4d 53 44 4f 53 35 2e 30(MSDOG5.0)占用8个字节,这个说明了微软不同的操作系统版本。修改这个值不影响文件系统的使用。
BPB从DBR的第12个字节开始,占用79个字节,其又分为25字节的分区参数块(BPB)和52字节的扩展分区参数块(扩展BPB),记录了有关该文件系统的重要信息,其中各个参数的含义见下表
偏移 |
长度(B) |
字段名与定义 |
说明 |
BPB |
|||
0X0B |
2 |
每扇区字节数 |
记录每个逻辑扇区的大小,其常见的值为512,但是并不是固定的值。该值可以由程序定义,合法值包括512、1024、2048、4096。 |
0X0D |
1 |
每簇扇区数 |
记录着文件系统的簇大小,即由多少个扇区组成一个簇。簇是FAT12,FAT16及FAT32文件系统下数据的最小存储单元,一个簇由一组连续的扇区组成,簇所含的扇区数必须是2的整数次幂,如1,2,4,8,16,32,64,128.在Windows 2000以前族最大值为64扇区,之后最大值为128。在FAT文件系统中,所有的簇是从2开始编号,每个簇都有一个自己的地址编号,但是所有的簇都位于数据区,在数据区之前没有簇。 |
0X0E |
2 |
DOS保留扇区数 |
DBR到FAT1表之间的扇区数,或者说是FAT1的开始扇区号,对于FAT32文件系统来说,该值的范围是32扇区到38扇区之间。 |
0X10 |
1 |
FAT个数 |
一般为2 |
0X11 |
2 |
未用 |
FAT32必须等于0,FAT12/FAT16为根目录中目录的个数 |
0X13 |
2 |
未用 |
FAT32必须等于0,FAT12/FAT16为扇区总数 |
0X15 |
1 |
介质描述符 |
描述磁盘介质的参数,根据磁盘性质的不同,取不同的值。0xF8标准值,可移动存储介质,常用 0xF0 |
0X16 |
2 |
未用 |
FAT32必须为0,FAT12/FAT16为一个FAT 表所占的扇区数。 |
0X18 |
2 |
每磁道扇区数 |
一般其值为63 |
0X1A |
2 |
磁头数 |
一般为255 |
0X1C |
4 |
隐藏扇区数 |
是MBR到DBR之间的扇区数,对于扩展分区中逻辑驱动顺来说,是其EBR到DBR。可以为0。 |
0X20 |
4 |
分区扇区总数 |
分区的总扇区数,也就是FAT32分区的大小 |
扩展BPB |
|||
0X24 |
4 |
每FAT扇区数 |
FAT表占用扇区数 |
0X28 |
2 |
标记 |
FAT2是否可用,2为可用,此域FAT32 特有 |
0X2A |
2 |
版本 |
FAT32版本号0.0,FAT32特有 |
0X2C |
4 |
根目录首簇号 |
分区在格式化的时候,格式化程序会在数据区中指派一个簇作为FAT32的根目录的开始,并把该簇号记录在BPB中。通常都是把数据区中的第一簇分配给根目录使用,也就是2号簇。 |
0X30 |
2 |
文件系统信息扇区号 |
FAT32文件系统在DBR的保留扇区中安排了一个文件系统信息扇区,用以记录数据区中空闲簇的数量及下一个可用的空闲簇的簇号,该扇区一般在分区的1号扇区,也就是紧跟在DBR之后的一个扇区。FSINFO(文件系统信息扇区)扇区号1,该扇区为操作系统提供关于空簇总数及下一可用簇的信息 |
0X32 |
2 |
DBR备份扇区号 |
FAT32文件系统在DBR的保留扇区中安排了一个DBR的备份,一般在6号扇区,也就是分区的第7个扇区,该备份扇区与原DBR扇区的内容完全一样,如果原DBR遭到破坏,可以用备份扇区号修复。 |
0X34 |
12 |
保留 |
|
0X40 |
1 |
BIOS驱动器号 |
这是BIOS的INT 13H所描述的设备号码,一般硬盘为80H,一般软盘为00H等 |
0X41 |
1 |
未用 |
|
0X42 |
1 |
扩展引导标记 |
用来确认后面的三个参数是否有效,FAT为29H |
0X43 |
4 |
卷序列号 |
磁盘序列号,通常为一随机数 |
0X47 |
11 |
卷标 |
用户设置的卷标ASCII,如果没有则4E 4F 20 4E 41 4D 45 20 20 20 20 即NO NAME。如果建立文件系统的时候指定了卷标,会保存在此 |
0X52 |
8 |
文件系统类型 |
使用ASCII码记录当前分区的文件系统类型,46 41 54 33 32 20 20 20即FAT32 |
Fat32的DBR引导程序占用420个字节,在98 之前的系统之下,这段代码负责完成DOS三个系统文件的装入; 2000之后的系统中,其负责完成将系统文件NTLDR装入。对于一个没有操作系统的分区来讲,这段代码是没有作用的。
0x5A~0x1FD:90~509共410字节,未使用。该部分没有明确的用途。
系统启动步骤:
在系统启动过程中, 磁盘的主引导记录MBR 中的引导记录 找到“可引导扇区” 的“引导代码”并将控制权交给它 , 由它找到适当的操作系统文件并进行加载。
注意: 一个FAT 卷即使不是可引导文件系统,也存在引导代码。
签名标志0xAA55
位置:一般位于文件系统的 1号 扇区。
作用:简言之就是记录文件系统的当前信息, FAT32 在保留扇区中添加了一个FSINFO扇区, 用以记录文件系统中的 “空闲簇的数量” 以及 “下一个可用簇的簇号”等信息,一共操作系统作为参考。
偏移 |
字节数 |
说明 |
00 |
4 |
扩展引导标志 52 52 61 41 |
04 |
480 |
未使用 |
1E4 |
4 |
FSINFO签名72 72 41 61 |
1E8 |
4 |
空闲簇数 |
1EC |
4 |
下一个可用簇号 |
1F0 |
14 |
未使用 |
1EE |
2 |
55 AA 结束标志 |
提示: 通常情况下,文件系统的2号扇区结尾也会被设置“55AA”标识 ; 6号扇区会有一个引导扇区的备份 ; 7号扇区应该是一个备份FSINFO 信息扇区,但很多时候与1号扇区的内容不完全相同;8号扇区可以看做是2号扇区的备份,他的结尾也会有一个“55AA” 标识。
位置: 紧跟在文件系统的“保留区”之后 ; 有两个数据结构完全相同的FAT(FAT,File Allocation Tbale 文件分配表)组成。
作用: FAT表项,描述文件系统内的簇分配状态,说明文件系统内数据所分配的连续簇的顺序关系(即表明文件或目录的下一簇的序号)。
数量: 通常情况下一个FAT 文件系统会有两个FAT 表, 但有时候也会允许只有一个FAT 表, FAT 表的具体个数记录在引导扇区的偏移 0x10 字节处。
位置: 因为FAT区位于文件系统的保留区之后,所以FAT1在文件系统中的位置可以通过引导记录中偏移0x0E~0x0F 字节处的“保留扇区”数得到。
FAT1表偏移 = 保留扇区数 * 每扇区字节数
FAT2 紧跟在FAT1之后, 它的位置可以通过FAT1的位置加上每个FAT 表的大小扇区数获得。
FAT2表的偏移 = FAT1表偏移+FAT表的大小
= (保留扇区数 + FAT表扇区数) * 每扇区字节数
FAT 表中记录了每个文件的簇链结构;
FAT 表中记录的与数据区簇对应的表项,从0号标记开始至当前数据区所分配的簇的最大数值,记录簇信息到FAT 项;但是注意:其中 0号~1号簇的值都是操作系统预先不留设定的特殊标记,而数据区的起始簇是2号簇。
表项数值 |
对应含义 |
0x00000000 |
空闲簇,即表示可用 |
0x00000001 |
保留簇 |
0x00000002 - 0x0FFFFFEF |
被占用的簇,其值指向下一个簇号 |
0x0FFFFFF0 - 0x0FFFFFF6 |
保留值 |
0x0FFFFFF7 |
坏簇 |
0x0FFFFFF8 - 0x0FFFFFFF |
文件最后一个簇 |
表项数值含义
FAT 表由一些列大小相等的表项组成,有如下特性:
FAT32 中每个簇的状态,使用32bit(4字节)记录在FAT表中。 FAT 表中的所有字节位置以 4个字节为单位进行划分;并以所有划分后的位置由0进行地址编号。“0号 和 1号”地址被系统保留并存储特殊标识内容。从 2号 地址开始, 每个地址对应于数据区的簇号, FAT 表中的地址编号与数据区中的簇号相同。 称FAT 中的这些四字节一组划分的项的地址为 FAT 表项, FAT表项中记录的值为FAT 表项值。
当文件系统创建时(就是格式化操作时), 分配给FAT 区域的空间将会被清空, 在FAT1与FAT2 的0号和1号表项写入特定值。 由于创建文件系统的同时,也会创建根目录, 也就是为根目录分配了一个簇空间,通常为2号簇,所以2号簇所对应的“2号FAT表项”也会被写入一个结束标记。
如果某个簇未被使用,他所对应的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”。
项内容填写规则:
在文件系统中新建文件时,如果新建的文件只有一个簇,为其分配的簇所对应的FAT表项将会被写入结束标记。如果新建的文件不只占用一个簇,则在其所占用的每个簇对应的FAT表项中写入为其分配的下一个簇的簇号,在最后一个簇对应的FAT 表项中写入结束标记。
新建目录时,只为其分配一个簇的空间,对应的FAT 表项中写入结束标记。当目录增大超过一个簇的大小时,将会在空闲空间中继续为其分配一个簇,并在FAT 表中为其建立FAT 表链以描述它所占用的簇的情况。
对文件或目录进行删除操作时,他们所对应的FAT 表项将会被清空,设置为0以表示其所对应的簇处于未分配的状态。
一个文件的"起始簇号"记录在它的目录项中, 该文件的 "其他簇" 则用一个簇连结构记录在FAT 表中。
如果一个簇所对应的FAT表项的表项值为非零, 则表明该簇已经被分配使用了,但是这时表项值可能为两种情况,一个是一个文件的下一个簇号值,也有可能是一个文件的结束标记0x0FFFFFFF,或者是一个坏簇标记0x0FFFFFF7 。
如果要寻找一个文件的下一个簇,只需要查看该文件的目录项中描述的起始簇号所对应的FAT项,如果该文件只有一个簇,则此处的值为一个结束标记0x0FFFFFFF;如果该文件不只一个簇,则此处的值是它的下一个簇的簇号。
查询簇连接结构模拟步骤:
当我们要寻找某个文件时, 首先从该文件的“目录项”中获取该文件的第一“簇”的簇号,然后根据“第一簇”的“簇号 N”,然后根据N 从FAT区的FAT表找出N簇号所对应的FAT 表项,查看FAT 表项的内容:
若是文件结束,该表项值为 0x0FFFFFFF; 若是没有结束,而该文件的大小超出一个簇,则N所对应的FAT表项的表项值为该文件下一个簇的簇号,然后再找到下一个簇号N+1 所对应的FAT表项,查看其表项值,依次类推,就推出了一个文件在FAT表中的 簇链连接结构; 也或者表项值为 0xFFFFFFF7 坏簇标识。
其他
查找FAT 表项: 要找到一个簇的FAT 表项,只要用他的 簇号乘以每个FAT 表项的字节数即可 。对于FAT32而言,每个FAT 表项占用4个四字节, 如果我们寻找9号簇的表项位置,则用 4*9=36,也就是说位于FAT 表内偏移36(0x24)字节处。
注意:
WinHex 提供了直接跳转到某个指定FAT 表项的功能。
文件系统大小的上限值却绝育FAT 项的大小。 簇链中的每个FAT 项记录着下一个簇的簇地址,FAT 项所能表示的数字有一个上限,这个上限也就是文件系统中的最大簇号。 FAT 32文件系统的FAT 项只使用了32bit 中的28bit ,因此只能描述 268435456个簇(实际上还要考略小于这个值,因为这其中还包含了结束标志及坏簇标志的保留值)。
操作系统通过检测FAT 表中的表项来确定文件系统中的各个簇是否被分配使用。当我们在Windows 下右击某个FAT 分区查看其属性时,显示的已用空间和未用空间就是根据FAT 表统计而来的。
作用: FAT32 的“数据区域”是真正用来存储用户数据的区域。 数据区域紧跟在FAT 区域之后,数据区域被划分为一个个的簇,所有的簇从2号开始编码,也就是说2号簇就是数据区域的起始位置。数据区的内容主要由三部分组成:根目录,子目录和文件内容。在数据区中是以“簇”为单位进行存储的,2号簇被分配给根目录使用。
虽然原则上FAT32 允许根目录位于数据区中的任何位置,但是“通常情况”下位于“2号簇”。也就是说根目录位于数据区域的起始位置。
定位根目录
首先要明确: 在FAT文件系统中,寻找第一簇(即2号簇)的位置是也就是寻找数据区的开始位置,并不是件简单的事情,因为它不是位于文件系统的起始处,而是位于数据区域的起始处。数据区域之前有保留区域和FAT 区域, 这两个区域都不使用FAT 表进行管理。因此,数据区以前的区域只能使用扇区地址(逻辑扇区地址),而无法使用簇地址。所以说,并不是每个逻辑卷地址都相应的有一个“逻辑文件系统地(内部以簇为单位)址”,FAT 系统就是个特别的例子。数据区的偏移如下计算可得:
数据区偏移 = (保留扇区数 + FAT表扇区数 * FAT表个数(通常为2)
+ (起始簇号-2) * 每簇扇区数) * 每扇区字节数
所以一般情况下,数据区的开始为根目录。
根目录分析
作用: 根目录在文件系统创建时即已被创建,其目的就是存储“子目录”(也称为文件夹)或 文件的“目录项”。
目录项大小:每个目录项的大小为 “32个字节”。
在文件系统刚刚创建,还没有存储任何数据时,根目录下没有任何内容,文件系统只是为根目录分配了一个簇的空间(通常为2号簇),将结束标记0x0FFFFFFF 写入该簇对应的FAT 表项,表示该簇已经被分配使用。这时候根目录分配的空间没有任何内容。 但是如果创建文件系统时指定卷标,则会在根目录下为其建立一个卷标目录项,该目录项占用“根目录”中的第一个目录项位置。
在根目录下新建目录或文件时,其实就是在为根目录分配的簇中为其建立目录项,如果需要则在未分配空间为其分配空间已存储数据内容。
目录项的基本特性
不管是根目录下还是子目录下的目录项,都有以下基本特性:
定义: 所有除根目录以外的目录度都称为子目录,不管是根目录的子目录,还是根目录的子目录的子目录。
过程: 子目录是在存储过程中根据用户需要建立的,随着目录建立的同时,会在为其分配的簇空间开始处建立“两个目录项”来描述 “子目录本身和其父目录” 的信息,以使父子目录间建立起联系。
FAT32文件系统中,在创建文件系统时就创建了根目录并且分配存储空间之外,其他所有目录只有在使用过程中根据需要建立。新建一个子目录时,在其父目录建立目录项,在空闲空间中为其分配一个簇,并对簇清零操作,同时将这个簇号记录在它的目录项。
创建子目录时在为其父目录分配的簇中建立目录项,目录项描述了该子目录的起始簇号; 在为子目录建立目录项的同时,也在为子目录分配的簇中,使用前两个目录项描述他与父目录的关系。
提示: 子目录的目录项中并不描述子目录的大小,要想知道子目录所占用的空间大小,可以从他的目录项中获得他的起始簇号并跟踪它的FAT 表链直到遇到结束标记为止。
目录项: 32字节长(短名称目录项32字节,长名称目录项1个或多个32字节;长名称目录项在前;若是长名称目录项长度为多个32字节则倒序排列,依然位于读文件名目录项前) 、 每个目录或者文件(文件夹)都有与其对应的目录项 、 作用(记住目录或文件夹的起始簇号)以及一些文件大小,文件名 等信息
根目录:
位置:FAT32 文件系统的根目录位于文件系统的数据区的第一簇(2号簇,也就是数据区的起始簇)
根目录创建时期: 当创建文件系统过程中,自动创建根目录(若当下根目录中未创建文件以及目录,则2号簇所对应的FAT 表项值为 0x0fffffff结束标记)
根目录作用:存储根文件系统中子目录以及文件的目录项。
文件系统中除去根目录以外,其他目录是子目录;目录与在其下创建的目录为父子关系;
根目录创建子目录或文件的意义: 在根目录中创建文件或子目录实质含义是在为根目录分配的簇中创建子目录/文件的目录项。
根目录创建子目录过程: 除根目录是是在创建文件系统时便创建完成外,(其他非根目录的均为)子目录,所有的子目录都是要在使用时才创建,子目录创建时同时在其为根目录中分配的簇中创建了子目录的目录项,并且同时在为该子目录分配的簇中创建目录项(使用前两个目录项描述该子目录与其父目录之间的关系);在子目录中创建下一级子目录或文件时,在为该子目录分配的簇中创建目录项,便需从“第三个目录项” 向后排序了。
目录区是由一个个目录项构成,类似于FAT表。其中每一个目录项占用32个字节,可以是代表长文件名目录项、文件目录项、子目录项等。对于短文件名格式的目录项,其参数的含义如下所示:
FAT32短文件名目录项参数表
时间格式:占2byte
高5位:代表小时
中6位:代表分钟
低5位:代表秒的1/2
日期格式:占2byte
高7位:代表从1980年开始的年数
中4位:代表月份
低5位:代表日期
文件起始地址偏移
文件起始地址 = (保留扇区数 + FAT表扇区数 * FAT表个数+
(文件起始簇号-2)*每簇扇区数)*每扇区字节数
文件名大小写:
FAT32根据文件目录项判断文件名大小写的方法(仅限8.3命名规则):
文件目录项0CH字节的值:
1. 此值为18H时,文件名和扩展名都小写。
2. 此值为10H时,文件名大写而扩展名小写。
3. 此值为08H时,文件名小写而扩展名大写。
4. 此值为00H时,文件名和扩展名都大写。
支持支持长文件名是 FAT32的一个很重要的特性。长文件名也是记录在目录项当中的,区别与短目录项的是,前者可能会占据好几个目录项。为了兼容低版本的OS或程序能正确读取长文件名文件,系统自动为所有长文件名文件创建了一个对应的短文件名,使对应数据既可以用长文件名寻址,也可以用短文件名寻址。不支持长文件名的OS或程序会忽略它认为不合法的短文件名字,而支持长文件名的OS或程序则会以长文件名为显式项来记录和编辑,并隐藏起短文件名。
当创建一个长文件名文件时,系统会自动加上对应的短文件名,其原则如下:
(1)、取长文件名的前6个字符加上"~1"形成短文件名,扩展名不变。
(2)、如果已存在这个文件名,则符号"~"后的数字递增,直到5。
那么系统是如何判断当前目录项是短文件名目录项呢还是长文件名目录项,这里关键是看目录项的第12个字节的值,如果为0x0F时则系统认为是长目录项。而如果是旧版本的系统看到第12个字节是0x0F则认为是异常而忽略掉。这里可以回过头去看一下短文件名目录项,第12个字节是文件属性字节,0x0F即为全1是无效的,所以系统认为是异常。系统将长文件名以13个字符为单位进行切割,每一组占据一个目录项。所以可能一个文件需要多个目录项,这时长文件名的各个目录项按倒序排列在目录表中,以防与其他文件名混淆。
注意:长文件名都是以unicode码存储。即每个字符占两个字节。每个长目录项可以最多存储长文件名的13个字符。文件名的位置也是不连续的。
u盘的根目录为JING,有两个文件第一个0123456789ABCDEFGHIJK.txt 第二个
abcdefg.txt 都是空文件。
由于长文件名长度为25(包括扩展名),所以需要2个长目录项。包括它本身的短目录项,共3个目录项。
注意:长文件名需要有结束字符0000,之后没有用的都置FFFF。否则会出现错误。如果刚好是13的倍数,则不可以用结束符0000。
校验值计算:
unsigned char ChkSum (unsigned char *pFcbName)
{
short FcbNameLen;
unsigned char Sum; //必须为无符号型.
Sum = 0;
for (FcbNameLen=11; FcbNameLen!=0; FcbNameLen--)
{
Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *pFcbName++;
}
return (Sum);
}
校验值在同一个文件名的每个长文件目录项都是一样的,因为都是计算该长文件名的校验值。校验的都是其短文件名目录中的内容,即校验其文件名的前6个字符加上~1和扩展名共11个字符长度。如上图为3a,其校验的内容为“012345~1TXT”共11个字符。
FAT32文件系统在删除文件的时候,仅仅是对其文件名进行处理,对于内容是不做任何处理的。对文件名的处理,就是把其所相关的所有Directory Entry的第一个byte都置为0xE5,此时就认为该文件已经被删除了。