一、FAT文件系统分为四个部分
参考别人的博客
1.
- 保留扇区(引导区)
最开始的位置,第一个保留扇区是引导区。包括基本的文件系统信息,比如它的类型和其它指向其它扇区的指针。通常包括操作系统启动调用代码。保留扇区的总数记录在引导扇区中的一个参数中。
- FAT区(文件分配表)
包含两份文件分配表,分区信息的映射表,指示簇是如何存储的。
- 根目录区
在根目录中存储文件和目录信息的目录表。
- 数据区域
实际文件和目录数据存储的区域。需要注意的是每个簇只能被一个文件占有。
主引导记录(主引导扇区),读设备时最开始读这个分区。
- MBR(master boot record)MBR 又称作主引导记录占用 Boot Sector 的前 446 个字节 ( 0 to 0x1BD ), 存放系统主引导程序 (它负责从活动分区中装载并运行系统引导程序).
- DPT 即主分区表占用 64 个字节 (0x1BE to 0x1FD), 记录了磁盘的基本分区信息,主分区表分为四个分区项,,每项 16 字节,分别记录了每个主分区的信息(因此最多可以有四个主分区).
- Boot Record ID 即引导区标记占用两个字节 (0x1FE and 0x1FF), 对于合法引导区,它等于 0xAA55,这是判别引导区是否合法的标志。
二、主引导扇区(MBR)的具体结构如下图所示:
Offset | Description | Size |
000h | Executable Code (Boots Computer) | 446 Bytes |
1BEh | 1st Partition Entry (See Next Table) | 16 Bytes |
1CEh | 2nd Partition Entry | 16 Bytes |
1DEh | 3rd Partition Entry | 16 Bytes |
1EEh | 4th Partition Entry | 16 Bytes |
1FEh | Executable Marker (55h AAh) | 2 Bytes |
USB hound 得到的数据
512 IN fa 31 c0 8e d8 8e c0 8e d0 bc 00 7c fb fc 89 e6 .1.............. 55.1.0(2)
bf 00 06 b9 00 01 f3 a5 ea dc 06 00 00 10 00 01 ................ 55.1.16
00 00 7c 00 00 00 00 00 00 00 00 00 00 80 3f 00 ..............?. 55.1.32
ff 00 b4 03 1e 0e 1f 3a 16 10 00 74 06 1f ea 36 .......:...t...6 55.1.48
e7 00 f0 3d fb 54 75 05 8c d8 fb eb 1d 80 fc 08 ...=.Tu......... 55.1.64
75 1b e8 81 00 8a 36 13 00 fe ce 8b 0e 15 00 86 u.....6......... 55.1.80
cd c0 e1 06 0a 0e 11 00 31 c0 f8 eb 65 80 fc 02 ........1...e... 55.1.96
72 cb 80 fc 04 77 c6 60 80 cc 40 50 be 00 00 c7 r....w.`..@P.... 55.1.112
04 10 00 30 e4 89 44 02 89 5c 04 8c 44 06 66 31 ...0..D..\..D.f1 55.1.128
c0 66 89 44 0c 88 f0 f6 26 11 00 88 cf 88 eb c0 .f.D....&....... 55.1.144
ef 06 81 e1 3f 00 01 c8 48 89 c7 a1 13 00 f7 26 ....?...H......& 55.1.160
11 00 f7 e3 01 f8 81 d2 00 00 89 44 08 89 54 0a ...........D..T. 55.1.176
58 30 c0 8a 16 10 00 e8 0c 00 88 26 03 00 61 a1 X0.........&..a. 55.1.192
02 00 1f ca 02 00 9c ff 1e 22 00 c3 80 fa 8f 7f ........."...... 55.1.208
04 88 16 2d 06 be 87 07 e8 8d 00 be be 07 31 c0 ...-..........1. 55.1.224
b9 04 00 f6 04 80 74 03 40 89 f5 81 c6 10 00 e2 ......t.@....... 55.1.240
f2 48 74 02 cd 18 bf 05 00 be 1d 06 c7 44 02 01 .Ht..........D.. 55.1.256
00 66 8b 46 08 66 89 44 08 b8 00 42 8a 16 2d 06 .f.F.f.D...B..-. 55.1.272
cd 13 73 0d 4f 74 49 30 e4 8a 16 2d 06 cd 13 eb ..s.OtI0...-.... 55.1.288
d8 a1 fe 7d 3d 55 aa 75 37 fa 66 a1 4c 00 66 a3 ....=U.u7.f.L.f. 55.1.304
3f 06 be 13 04 8b 04 48 89 04 c1 e0 06 8e c0 31 ?......H.......1 55.1.320
ff be 1d 06 b9 60 00 fc f3 a5 c7 06 4c 00 17 00 .....`......L... 55.1.336
a3 4e 00 fb 8a 16 2d 06 89 ee fa ea 00 7c 00 00 .N....-......... 55.1.352
be aa 07 e8 02 00 eb fe ac 20 c0 74 09 b4 0e bb ......... .t.... 55.1.368
07 00 cd 10 eb f2 c3 53 74 61 72 74 20 62 6f 6f .......Start boo 55.1.384
74 69 6e 67 20 66 72 6f 6d 20 55 53 42 20 64 65 ting from USB de 55.1.400
76 69 63 65 2e 2e 2e 0d 0a 00 42 6f 6f 74 20 66 vice......Boot f 55.1.416
61 69 6c 65 64 00 00 00 ea eb d4 ca 00 00 00 00 ailed........... 55.1.432 第一分区
硬盘分区表 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 55.1.448 第二分区
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 55.1.464 第三分区
00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 04 ................ 55.1.480 第四分区
05 00 0b fe ff b3 00 01 00 00 80 8c e8 00 55 aa ..............U. 55.1.496
过256扇区后是这个分区 *512byte=7.2G
硬盘分区表
地址 | 字节数 | 描述 |
00~00 | 1 | 可引导标志0x00不可引导,0x80可引导 |
01~03 | 3 | 分区起始CHS地址 |
04~04 | 1 | 分区类型 |
05~07 | 3 | 分区结束CHS地址 |
08~0B | 4 | 分区起始LBA地址 |
0C~0F | 4 | 分区大小扇区数 |
分区起始CHS地址(U盘可以直接根据扇区,簇来寻址。就不用考虑了)
第一字节用于记录分区起始磁头号,第二字节低六位用于记录分区起始扇区号,用10bit记录分区起始柱面号:第二个字节的高两位作为起始柱面的高两位,第三个字节作为分区起始柱面的低八位。
三、DBR分区,读文件系统时最开始读这个分区。winhex 读取的数据
【1】0x00~0x02:3 个字节,跳转指令。 【2】0x03~0x0A:8 个字节,文件系统标志和版本号,这里为 MSDOC5.0。
【3】0x0B~0x0C:2 个字节,每扇区字节数,512(0X02 00)。
【4】0x0D~0x0D:1 个字节,每簇扇区数,8(0x08)。 【5】0x0E~0x0F:2 个字节,保留扇区数,2272(0x08 E0)。 加上256(MBR分区)=2528。FAT分区表从逻辑地址2528扇区开始【6】0x10~0x10:1 个字节,FAT 表个数,2。 【7】0x11~0x12:2 个字节,根目录最多可容纳的目录项数,FAT12/16 通常为 512。FAT32 不使用此处值,置 0。 【8】0x13~0x14:2 个字节,扇区总数,小于 32MB 时使用该处存放。超过 32MB 时使用偏移 0x20~0x23 字节处的 4 字节存放。笔者的 SD 卡容量为 2GB,所以不使用该处,置 0. 【9】0x15~0x15:1 个字节,介质描述符,0xF8 表示本地硬盘。 【10】0x16~0x17:2 个字节,每个 FAT 表的大小扇区数(FAT12/16 使用,FAT32 不使用此处,置 0)。 【11】0x18~0x19:2 个字节,每磁道扇区数,63(0x00 3F)。 【12】0x1A~0x1B:2 个字节磁头数,255(0x00 FF)。 【13】0x1C~0x1F:4 个字节,分区前已使用扇区数,63(0x00 00 00 3F)。保留区,数据地址要加上这个。这个数据就是相对于 MBR的地址偏移量,MBR 的扇区地址才是整个U盘(SD卡)的物理扇区号为 0 的那个地址,也就是说文件系统并不是处在整个 U盘(SD) 卡最开始的地方,它处在 MBR所处的保留区之后。U盘批量传输数据时,地址是逻辑扇区地址。
【14】0x20~0x23:4 个字节,文件系统大小扇区数,15646657(0x 00 EEBF C1)。
【15】0x24~0x27:4 个字节,每个 FAT 表的大小扇区数,15248(0x 00 00 3B 90)。 7.4M 【16】0x28~0x29:2 个字节,标记。 【17】0x2A~0x2B:2 个字节,版本号。 【18】0x2C~0x2F:4 个字节,根目录簇号,2。(虽然在 FAT32 文件系统下,根目录可以存放在数据区的任何位置,但是通常情况下还是起始于 2 号簇) 【19】0x30~0x31:2 个字节,FSINFO(文件系统信息扇区)扇区号,1。(上图的标注即用黄色条纹的标注有误,请读者注意)该扇区为操作系统提供关于空簇总数及下一可用簇的信息。 【20】0x32~0x33:2 个字节,备份引导扇区的位置,6。(上图的标注即用黄色条纹的标注有误,请读者注意)备份引导扇区总是位于文件系统的 6 号扇区。 【21】0x34~0x3F:12 个字节,未使用。 【22】0x40~0x40:1 个字节,BIOS INT 13H 设备号,0x80。(这个我也不知道什么意思☺) 【23】0x41~0x41:1 个字节,未用。 【24】0x42~0x42:1 个字节,扩展引导标志。0x29。 【25】0x43~0x46:1 个字节,卷序列号。通常为一个随机值。 【26】0x47~0x51:11 个字节,卷标(ASCII 码),如果建立文件系统的时候指定了卷标,会保存在此。笔者当时没有指定卷表,上图中的 YCY 是后来指定的。 【27】0x52~0x59:8 个字节,文件系统格式的 ASCII 码,FAT32。 【28】0x5A~0x1FD:410 个字节,未使用。该部分没有明确的用途。【29】0x1FE~0x1FF:签名标志“55 AA”。
四、文件分配表FAT
位于保留区后的是 FAT 区,有两个完全相同的 FAT(File Allocation Table, 文件分配表)表组成。
1. FAT32 中每个簇的簇地址,是有 32bit(4 个字节)记录在 FAT 表中。FAT 表中的所有字节位置以4 字节为单位进行划分,并对所有划分后的位置由 0 进行地址编号。0 号地址与 1 号地址被系统保留并存储特殊标志内容。从 2 号地址开始,每个地址对应于数据区的簇号,FAT 表中的地址编号与数据区中的簇号相同。我们称 FAT 表中的这些地址为 FAT 表项,FAT 表项中记录的值称为 FAT表项值。
2. 当文件系统被创建,也就是进行格式化操作时,分配给 FAT 区域的空间将会被清空,在 FAT1 与FAT2 的 0 号表项与 1 号表项写入特定值。由于创建文件系统的同时也会创建根目录,也就是为根目录分配了一个簇空间,通常为 2 号簇,所以 2 号簇所对应的 2 号 FAT 表项也会被写入一个结束标记。3. 如果某个簇未被分配使用,它所对应的 FAT 表项内的 FAT 表项值即用 0 进行填充,表示该 FAT 表项所对应的簇未被分配。
4. 当某个簇已被分配使用时,则它对应的 FAT 表项内的 FAT 表项值也就是该文件的下一个存储位置的簇号。如果该文件结束于该簇,则在它的 FAT 表项中记录的是一个文件结束标记,对于 FAT32而言,代表文件结束的 FAT 表项值为 0x0FFFFFFF。
5. 如果某个簇存在坏扇区,则整个簇会用 FAT 表项值 0xFFFFFF7 标记为坏簇,不再使用,这个坏簇标记就记录在它所对应的 FAT 表项中。 6. 由于簇号起始于 2 号,所以 FAT 表项的 0 号表项与 1 号表项不与任何簇对应。FAT32 的 0 号表项值总是“F8FFFF0F”。如上图所示。 7. 1 号表项可能被用于记录脏标志,以说明文件系统没有被正常卸载或者磁盘表面存在错误。不过这个值并不重要。正常情况下 1 号表项的值为“FFFFFFFF”或“FFFFFF0F”。 8. 在文件系统中新建文件时,如果新建的文件只占用一个簇,为其分配的簇对应的 FAT 表项将会写入结束标记。如果新建的文件不只占用一个簇,则在其所占用的每个簇对应的 FAT 表项中写入为其分配的下一簇的簇号,在最后一个簇对应的 FAT 表象中写入结束标记。 9. 新建目录时,只为其分配一个簇的空间,对应的 FAT 表项中写入结束标记。当目录增大超出一个簇的大小时,将会在空闲空间中继续为其分配一个簇,并在 FAT 表中为其建立 FAT 表链以描述它所占用的簇情况。 10. 对文件或目录进行操作时,他们所对应的 FAT 表项将会被清空,设置为 0 以表示其所对应的簇处于未分配状态。
五、根目录(数据区的第一簇)
定位一个 FAT32 文件系统的数据起始处,可以通过引导扇区的相关参数计算出来。
1.从引导扇区的偏移 0x0E~0x0F 字节处得到保留扇区。
2.从偏移 0x10 字节处得到 FAT 表的个数。
3.从偏移 0x24~0x27 字节处得到每个 FAT 表的大小扇区数。
4.利用如下公式计算:
保留扇区数 + 每个 FAT 表大小扇区数 × FAT 表个数 = 数据区起始扇区号256+2272+15248*2=33024
计算其他已知簇号的扇区号,还要由引导扇区的偏移 0x0D 字节处查找到每个簇大小扇区数,并使用如下公式计算: 某簇起始扇区号 = 保留扇区数 + 每个 FAT 表大小扇区数 × FAT 表个数 + (该簇簇号 - 2) × 每簇扇区数
根目录在文件系统建立时即已被创建,其目的就是存储目录(也称文件夹)或文件的目录项。每个目录项的大小为 32 个字节。
卷标Kingston
接下来是子目录
前两个目录表项 是当前目录(.)和父目录 ( .. )
下面开始介绍目录项(短文件名目录项)
如果文件名不足 8 个字符,用 0x20 进行填充。
超过 8 个字符时则会被截短,因为短文件名目录项中没有足够的空间记录超出的部分。截短的方法是取文件名的前 6 个字符加上“~1”(如果有同名文件,则会依次递增该数值),然后加上其扩展名。 如果是子目录,则将扩展名部分用“0x20”进行填充。 为了解决长文件名的问题,FAT 文件系统又增加了一种“长文件名”目录项结构。其从 windows95 开始,不管文件名的长度是否超过 8 个字符,都会同时为其创建短文件名目录项和长文件名目录项,因为短文件名不区分大小写,而长文件名则是区分大小写的。
具体解释如下:
【1】0x00~0x00:1 个字节,如果该目录项正在使用中,则为文件名或子目录名的第一个字符。 0x00:说明该目录项未被分配使用。 0xE5:说明该目录项曾经被使用过,但是现在已被删除。目前处于未分配状态 【2】0x01~0x0A:10 个字节,文件名的第 2 至第 11 个 ASCII 码,除扩展名外,如果文件的名字不足 8个字符则用 0x20 进行填充。 【3】0x0B~0x0B:1 个字节,所描述文件的属性 0x01-只读 0x02-隐藏 0x04-系统文件 0x08-卷标 0x0F-为此值时表示该目录项为长文件名目录项 0x10-目录 0x20-存档 【4】0x0C~0x0C:1 字节,保留 【5】0x0D~0x0D:1 个字节,文件穿件的时间,精确到创建时刻的十分之一秒 【6】0x0E~0x0F:2 个字节,文件创建的时间——时分秒 两个字节的 16bit 被划分为 3 个部分: 0~4bit 为秒,以 2 秒为单位,有效值为 0~29,可以表示的时刻为 0~58 5~10bit 为分,有效值为 0~59 11~15bit 为时,有效值为 0~23【7】0x10~0x11:2 个字节,文件创立的日期,16bit 也划分为三个部分:
0~4bit 为日,有效值为 1~31 5~10bit 为月,有效值为 1~12 11~15bit 为时,有效值为 0~127,这是一个相对于 1980 年的年数值,也就是说该值加上 1980即为文件创建的日期值。该部分笔者就不再举例就计算了,原理和计算创建时间是一样的。请读者自己去计算。 【8】0x12~0x13:2 个字节,最后访问日期。 【9】0x14~0x15:2 个字节,文件起始簇号的高两个字节。 【10】0x16~0x17:2 个字节,文件最后修改的时间。【11】0x18~0x19:2 个字节,文件最后被修改时的日期。
【12】0x1A~0x1B:文件内容起始簇号的低两个字节,与 0x14~0x15 字节处的高两个字节组成文件内容起始簇号。 【13】0x1C~0x1F:文件内容大小字节数,只对文件有效,子目录的目录项此处全部设置为 0。