1. TF卡空间是如何分配的?
下面以4GB TF卡为例,通过WinHex工具进行分析,其空间分配如下图所示:
FAT32把目录当做文件来管理,所以没有独立的目录区,所有的文件目录项都是在数据区里面的。
2. 启动扇区 (DBR)
DBR(DOS BOOT RECORD,DOS引导记录),位于柱面0,磁头1,扇区1,即逻辑扇区0 ;
DBR包括:
• 一个引导程序: DOS 引导程序完成DOS系统文件(IO.SYS,MSDOS.SYS)的定位与装载
• 一个BPB: BPB用来描述本DOS分区的磁盘信息,比如:本分区的起始扇区、 结束扇区等等
注意:搜索DBR的标志:
• FAT16的DBR:EB 3C 90,无备份的DBR
• FAT32的DBR:EB 58 90,有备份的DBR,通常在该分区的第6扇区
• NTFS的DBR: EB 52 90,有备份的DBR,通常在该分区的最后一个扇区
2.1 DBR组成
偏移量 |
长度/字节 |
组成部分 |
00H |
3 |
跳转指令 |
03H |
8 |
操作系统厂商标识及版本号 |
08H |
80 |
分区参数表(又称BPB),里面存放着对该分区进行读写操作时所必备的参数 |
5AH |
420 |
DOS引导代码,它负责把DOS引导文件IO.SYS、MSDOS.SYS装入内存 |
FEH |
2 |
结束标志字”55AA” |
2.2 BPB(BIOS Parameter Block)的组成
3. FAT(File Allocation Table)文件分区表
• 簇(Cluster)
是文件数据区被划分成的具有大小相等的区域用于磁盘文件的计量分配单位。
• 文件分配表
是位于磁盘0扇区上的一个特殊的文件,它包含了磁盘上的文件的大小以及文件存放的簇的位置等信息。
• 文件的首簇号
存放在FDT(根目录)登记项中,后续簇号存放在FAT中。
FAT表以簇为单位,标识分区中空间的使用情况(每个标识占4字节)。其示意图如下图所示:
FAT前2簇为保留簇(簇0和簇1),不分配给文件使用,其内容含义如下所示:
• FAT16:F8 FF FF
• FAT32:F8 FF FF 0F FF FF FF FF
一个FAT表项值表明了文件占用的一个簇号并指明下一簇号的位置。
FAT表按顺序依次记录了该盘各簇的使用情况,是一种位示图法。每簇的使用情况用32位二进制填写,未被分配的簇相应位置写零;坏簇相应位置填入特定值;已分配的簇相应位置填入非零值,具体为:如果该簇是文件的最后一簇,填入的值为FFFFFF0FH(即0x0FFFFFFF),如果该簇不是文件的最后一簇,填入的值为该文件占用的下一个簇的簇号,这样,正好将文件占用的各簇构成一个簇链,保存在FAT表中。0000000H、00000001H两簇号不使用,其对应的两个DWORD位置(FAT表开头的8个字节)用来存放该盘介质类型编号。
FAT表的大小就由该逻辑盘数据区共有多少簇所决定,取整数个扇区。
当文件系统被创建,也就是进行格式化操作时,分配给FAT区域的空间将会被清空,在FAT1与FAT2的0号表项与1号表项写入特定值。由于创建文件系统的同时也会创建根目录,也就是为根目录分配了一个簇空间,通常为2号簇,所以2号簇所对应的2号FAT表项也会被写入一个结束标记,如上图所示。
当某个簇已被分配使用时,则它对应的FAT表项内的FAT表项值也就是该文件的下一个存储位置的簇号。如果该文件结束于该簇,则在它的FAT表项中记录的是一个文件结束标记,对于FAT32而言,代表文件结束的FAT表项值为0x0FFFFFFF。
如果某个簇存在坏扇区,则整个簇会用FAT表项值0xFFFFFF7标记为坏簇,不再使用,这个坏簇标记就记录在它所对应的FAT表项中。
在文件系统中新建文件时,如果新建的文件只占用一个簇,为其分配的簇对应的FAT表项将会写入结束标记。如果新建的文件不只占用一个簇,则在其所占用的每个簇对应的FAT表项中写入为其分配的下一簇的簇号,在最后一个簇对应的FAT表象中写入结束标记。
新建目录时,只为其分配一个簇的空间,对应的FAT表项中写入结束标记。当目录增大超出一个簇的大小时,将会在空闲空间中继续为其分配一个簇,并在FAT表中为其建立FAT表链以描述它所占用的簇情况。
对文件或目录进行操作时,他们所对应的FAT表项将会被清空,设置为0以表示其所对应的簇处于未分配状态。
4. FDT (File Directory Table) 文件目录表
文件目录表(FDT)是由若干个32字节的表项构成的。它记录着每个文件(目录)的如下内容:
• 文件名
• 扩展名
• 是否支持长文件名
• 起始单元(即起始簇编号,这是最重要的)
• 文件的属性
• 大小
• 创建日期等内容
用FORMAT命令对磁盘进行格式化的时候,就已经为整个磁盘建立了一个根目录FDT。
根目录下的所有文件及其子目录在根目录的文件目录表(FDT)中都有一个“目录登记项”或简称为“目录项”。每个目录登记项占用32个字节,分为8个区域,提供有关文件或子目录的信息。其详细描述如下图所示:
• 0-- 7字节: 文件正名。
• 8--10字节: 文件扩展名。
• 11字节:文件属性,按二进制位定义,最高两位保留未用,0至5位分别是只读位、隐藏位、系统位、卷标位、子目录位、归档位。
• 12--13:字节仅长文件名目录项用,用来存储其对应的短文件名目录项的文件名字节校验和等。
• 14--15:字节 24位二进制的文件建立时间,其中的高5位为小时,次6位为分钟。
• 16--17字节:16位二进制的文件建立日期,其中的高7位为相对于1980年的年份值,次4位为月份,后5位为月内日期。
• 18--19字节: 16位二进制的文件最新访问日期,定义同(6)。
• 20--21字节 起始簇号的高16位。
• 22--23字节 16位二进制的文件最新修改时间,其中的高5位为小时,次6位为分钟,后5位的二倍为秒数。
• 24--25字节 16位二进制的文件最新修改日期,定义同(6)。
• 26--27字节 起始簇号的低16位。
• 28--31字节 32位的文件字节长度。
格式为Little Endian, 即高位字节位于高地址。
4.1 删除文件之后的变化
• 在FAT文件系统中,文件删除时,操作系统找到对应的目录文件表将第一个字节修改成“E5”标志
• 同时,将FAT文件分配表相应的项目清空,供其它程序使用
• 文件的数据并没有被覆盖,而是实际存在,但对操作系统而言,是无效的垃圾数据
• 当新文件需要存放时,新的数据可直接在原来数据位置上写入
4.2 根目录(root)
根目录区(ROOT区)不再是固定区域、固定大小,可看作是数据区的一部分。因为根目录已改为根目录文件,采用与子目录文件相同的管理方式,一般情况下从第2簇开始使用,大小视需要增加,因此根目录下的文件数目不再受最多512的限制。
虽然原则上FAT32允许根目录位于数据去的任何位置,但通常情况下它都位于2号簇。
4.2.1 定位根目录
在FAT32文件系统中,寻找第一簇(即2号簇)的位置也就是寻找数据区的开始位置,这并不是一件容易的事,因为它不是位于文件系统开始处,而是位于数据区。在数据区前面是保留区域和FAT区域,这两个区域都不使用FAT表进行管理。因此,数据区以前的区域只能使用扇区地址(逻辑卷地址),而无法使用簇地址。
要想定位一个FAT32文件系统的数据起始处,可以通过引导扇区的相关参数计算出来。
1) 从引导扇区的偏移0x0E~0x0F字节处得到保留扇区。
2) 从偏移0x10字节处得到FAT表的个数。
3) 从偏移0x24~0x27字节处得到每个FAT表的大小扇区数。
4) 利用如下公式计算:
保留扇区数+ 每个FAT表大小扇区数 × FAT表个数 = 数据区起始扇区号
要想计算其它已知簇号的扇区号,还要由引导扇区的偏移0x0D字节处查找到每个簇大小扇区数,并使用如下公式计算:
某簇起始扇区号 = 保留扇区数 + 每个FAT表大小扇区数 × FAT表个数 + (该簇簇号 - 2) × 每簇扇区数
4.2.2 根目录分析
根目录在文件系统建立时即已被创建,其目的就是存储目录(也称文件夹)或文件的目录项。每个目录项的大小为32个字节。
文件系统刚被创建时,还没有存储任何数据时,根目录下没有任何内容,文件系统只是为根目录分配了一个簇的空间(通常为2号簇),将结束标记写入该簇对应的FAT表项,表示该簇已经被分配使用。这时候,为根目录分配的空间没有任何内容。但如果在创建文件系统的时候是定了卷标,则会在根目录下为其建立一个卷标目录项,该目录项占用根目录中的第一个目录项位置。
不管是根目录还是子目录下的目录项,都具有以下的基本特性:
1) 为文件或子目录分配的第一个簇的簇号记录在它的目录项中,其他后续簇则由FAT表中的FAT表链进行跟踪。
2) 目录项中除记录子目录或文件起始簇号外,还记录它的名字、大小(子目录没有大小)、时间值等信息。
3) 每个子目录或文件除具有一个短文件目录项外,还会有长文件名目录项。
4) 短文件名目录项固定占用32字节,长文件名目录项则根据需要占用1个或者若干个32字节。
5) 对于同一个子目录或文件,它的长文件名目录项存放在它的短文件名目录项之前,如果长文件名目录项占用多个32字节,则按倒序存放于段文件名目录项之前。
4.3 文件定位
在DBR中有记录根目录位置的信息(2CH: 磁盘根目录的起始簇号),通过查询根目录文件表FDT,找到相应的文件和目录的信息,在FDT记录了文件的名称、属性、创建时间、修改时间信息、还记录了文件的起始簇号,文件的实际大小等信息。
有了根目录的起始簇号,就可计算得到此簇的起始扇区号:
某簇起始扇区号 = 保留扇区数 + 每个FAT表大小扇区数 × FAT表个数 + (该簇簇号 - 2) × 每簇扇区数
根据以上公式,可计算得到:
根目录起始扇区号 = 36(0x24) + 7566 (0x1D8E) x 2 + (2-2) x 8= 15168
在DBR中,根目录的起始簇号如下图所示: