FAT 的全称是File Allocation Table(文件分配表系统),FAT 文件系统1982年开始应用于MS- DOS 中。
FAT 文件系统主要的优点是它可以被多种操作系统访问,如MS- DOS , Windows 所有系列和OS/2 等。这一文件系统在使用时遵循8.3 命名规则(即文件名最多为8 个字符,扩展名为3 个字符)。同时FAT 文件系统无法支持系统高级容错特性,不具有内部安全特性等。FAT32 是FAT16 文件系统的派生,比FAT16 支持更小的簇和更大的分区,这就使得FAT32 分区的空间分配更有效率。
我用的卡是TF卡。
完整的FAT32 文件系统包括DBR(DOS BOOT RECORD )操作系统引导记录区),FAT1(文件分配表1),FAT2(文件分配表2),根目录和数据,剩余扇区。
1. DBR(DOS BOOT RECORD)
DBR 通常占用分区的第0 扇区共512 个字节(特殊情况也要占用其它保留扇区)。在这512 个字节中,其实又是由跳转指令,厂商标志和操作系统版本号,BPB(BIOS Parameter Block),扩展BPB,OS 引导程序,结束标志几部分组成。以FAT32 为例说明分区DBR 各字节的含义。
SD卡上第0扇区数据:
现在来解释上面数据内容:
1.EB 58 90 jmpBoot 跳转指令。占3个字节。
2.从0x03~0x0A 是OEM名。占8个字节的字符串,标识了格式化该分区的操作系统的名称和版本号。
3.0x0B和0x0C,2个字节,表示一个扇区的字节数。这里表示512bytes/sector。
4. 0x0D表示,每个簇所拥有的扇区数。他的表示都是2
的次方(512
字节1
、2
、4
、8
、16
、32
、64
扇区),比如8
个扇区构成一个簇,它的簇大小就是8
,16
进制表示为8H
5.0x0E~0x0F 2个字节表示保留扇区数。即DBR
到FAT
表之间的扇区总数。 这里为22H,即34个保留扇区。
6.0x10 表示FAT计数。
表示该分区上的FAT
表共有几个副本,一般情况都为2
(注:在重建DBR
的情况下可以灵活调配)。
7.0x16~0x17 表示单个FAT表的扇区总数,通过次参数配合上面的参数就能够定位到根目录也就是Root,公式为:保留扇区+FAT表数量*每FAT扇区数=根目录的地址。这里为F8H
7....剩下的,直接看图吧。。。
要注意的是,SD卡中,采用小端模式存储的16位进制数据。从SD卡中读出数据,要用转换成大端模式。使用struct FAT32_BPB结构体,可以方便的读出SD卡中文件系统的相关信息。函数lb2bb()实现的是小端模式存储和大端模式存储的转换。
2 FAT
FAT 表记录了磁盘数据文件的存储链表,对于数据的读取而言是极其重要的,以至于Microsoft 为其开发的FAT 文件系统中的FAT 表创建了一份备份,就是我们看到的FAT2。FAT2 与FAT1 的内容通常是即时同步的,也就是说如果通过正常的系统读写对FAT1 做了更改,那么FAT2 也同样被更新。如果从这个角度来看,系统的这个功能在数据恢复时是个天灾。
文件分配表区(FAT)是FAT 文件系统管理磁盘空间和文件的最重要区域,它保存逻辑盘数据区各簇使用情况信息,采用位示图法来表示。文件所占用的的存储空间及空闲空间的管理都是通过FAT 实现的。FAT 区共保存了两个相同的文件分配表,便于第一个损坏时,还有第二个可用。FAT 表的大小由该逻辑盘数据区共有多少簇所决定,取整数个扇区。
数据区中每簇的使用情况通过查找其在FAT 表中相应位置的填充值可知晓。
FAT32 表中每簇.片用四个字(32 位)表示,开头的8 个字节用来存放该盘介质类型编号、因此有效簇从02H 开始使用。02H簇的使用情况由08H- 0BH 字节组成的32 位二进制数指示出来,03H 簇的使用情况由0CH- 0FH 字节组成的32 位二进制数指示出来,依此类推。未被分配使用和已回收的簇相应位置写零,坏簇相应位置填入特定0FFFFFF7H
标识,已分配的簇相应位置填入非零值,如果该簇是文件的最后一簇,填入的值为0FFFFFFFH,如果该簇不是文件的最后一簇,填入的值为该文件.占用的下一个簇的簇写,这样,正好将文件占用的各簇构成一个簇链,保存在FAT32 表中。FAT32 的文件分配表的数抓结构依然和FAT16 相同,所不同的是,FAT32 将记录簇链的二进制位数扩展到了32 位,故而这种文件系统称为FAT32。32
位二进制位的簇链决定了FAT 表最大可以寻址2T 个簇。这样即使簇的大小为1 扇区,理论上仍然能够寻址1TB 范围内的分区。但实际中FAT32 是不能寻址这样大的空间的,随着分区空间大小的增加,FAT 表的记录数会变得臃肿不堪,严重影响系统的性能。所以在实际中通常不格式化超过32GB 的FAT32 分区。分区变大时,如果簇很小,文件分配表也随之变大。仍然会有上面的效率问题存在。既要有效
地读写大文件,又要最大可能的减少空间的浪费。
根据FAT 文件白皮书提到的, FAT1 起始地址 = BPB_RsvdsecCnt*BPB_BytsPersec,得到起始地址为38 * 512 = 0x4C00.由下图可看出,与实际相符
在 0x4C00 的位置打头的就是0f ff ff f8 ff ff ff ff,这个就是FAT1 开始的数据与计算的结果是一样的,FAT 存放的是文件使用的簇号列表,一个簇号的存放占用四个字节,而且前两个簇是系统使用的空间,也就是所从第三个簇才是用户自定义的簇号存放.
再计算 FAT1 的大小,根据BPB_FATsz32 和BPB_BytsPersec,一个FAT 的大小是BPB_FATsz32*BPB_BytsPersec=3765 * 512,所以FAT2 的起始地址就是0x4C00+BPB_FATsz32*BPB_BytsPersec=0x1DB600,用WinHex 查看这部分数据,和计算结果是一样的。
FAT2和FAT1大小一样,之后便是根目录起始地址了,计算得到0x3B2000。
0x3B2000 开始的32 字节内容的意义。
(1).对于短文件名,系统将文件名分成两部分进行存储,即主文件名+扩展名。
0x0~0x7 字节记录文件的主文件名,0x8~0xA 记录文件的扩展名,取文件名中的ASCII 码值。
不记录主文件名与扩展名之间的"." 主文件名不足8 个字符以空白符(20H)填充,扩展名不足3 个字符同样以空白符(20H)填充。0x0 偏移处的取值若为00H,表明目录项为空;若为
E5H,表明目录项曾被使用,但对应的文件或文件夹已被删除。(这也是误删除后恢复的理论依据)。文件名中的第一个字符若为“.”或“..”表示这个簇记录的是一个子目录的目录项。“.”代表当前目录;“..”代表上级目录(和我们在dos
或windows 中的使用意思是一样的,如果磁盘数据被破坏,就可以通过这两个目录项的具体参数推算磁盘的数据区的起始位置,猜测簇的大小等等,故而是比较重要的)。
(2)、0xB 的属性字段:可以看作系统将0xB 的一个字节分成8 位,用其中的一位代表某种属性的有或无。这样,一个字节中的8 位每位取不同的值就能反映各个属性的不同取值了。如00000101 就表示这是个文件,属性是只读、系统。
数据区域地址=
根目录开始地址+(文件起始簇号-0x02)* BPB_BytsPersec *BPB_SecPerClus.