FAT12是Microsoft公司DOS操作系统所支持的文件系统之一,此外还有FAT16和FAT32,之后会分别详述这些文件系统。当软盘被标准格式化后,磁盘被格式化为:每磁头80个柱面(磁道),每个柱面有18个扇区,每个扇区有512字节空间。所以标准软盘的总空间(容量)为:
2*80*18*512=1474560B=1440K=1.44M
FAT12文件系统将按照下表所示的方式划分全部的容量,即文件系统数据结构:
FAT12 2880扇区 (1474560B) | 逻辑扇区 | 占用扇区 | 内容 | 磁盘CHS参数(磁头/柱面/扇区) |
---|---|---|---|---|
0 | 1(512B) | 引导程序 | 起:0/0/1 | |
1 | 9(4608B) | FAT文件分配表1 | 起:0/0/2 止:0/0/10 | |
10 | 9(4608B) | FAT文件分配表2 | 起:0/0/11 止:1/0/1 | |
19 | 14(9728B) | 根目录 | ||
33 | 14(9728B) | 文件数据区 |
逻辑扇区(0):
操作系统之所以认识FAT12格式的磁盘,其秘密就在于逻辑0扇区这512B上。如果这512字节的最后两个字节的内容分别是55和AA(0xAA55低字节在前,高字节在后)的话,BIOS在启动时会将这个扇区读取到0:7C00h-0:7DFFh处,然后跳转到0:7C00h处继续执行指令,操作系统即用此来达到引导系统的目的,而这个磁盘就称为可引导磁盘。操作系统标识FAT12文件系统是因为在逻辑0扇区(即引导扇区)处还存储着一个特定的数据结构,此结构有固定的格式,在操作系统将此磁盘格式化时自动生成,具体数据结构如下表所示:
标识 | 偏移量 | 类型 | 大小 | 说明 | 默认值 |
---|---|---|---|---|---|
0 | db | 3 | 跳转指令 | ||
BS_OEMName | 3 | db | 8 | OEM字符串,必须为8个字符,不足以空格填空 | MSWIN4.1 |
BPB_BytsPerSec | 11 | dw | 2 | 每扇区字节数 | 200h |
BPB_SecPerClus | 13 | db | 1 | 每簇占用的扇区数 | 1 |
BPB_RsvdSecCnt | 14 | dw | 2 | 保留扇区数 | 1 |
BPB_NumFATs | 16 | db | 1 | FAT表的记录数 | 2 |
BPB_RootEntCnt | 17 | dw | 2 | 最大根目录文件数 | 0e0h |
BPB_TotSec16 | 19 | dw | 2 | 逻辑扇区总数 | 0b40h |
BPB_Media | 21 | db | 1 | 媒体描述符 | 0f0h |
BPB_FATSz16 | 22 | dw | 2 | 每个FAT占用扇区数 | 9 |
BPB_SecPerTrk | 24 | dw | 2 | 每个磁道扇区数 | 12h |
BPB_NumHeads | 26 | dw | 2 | 磁头数 | 2 |
BPB_HiddSec | 28 | dd | 4 | 隐藏扇区数 | 0 |
BPB_TotSec32 | 32 | dd | 4 | 如果BPB_TotSec16是0,则在这里记录扇区总数 | 0 |
BS_DrvNum | 36 | db | 1 | 中断13的驱动器号 | 0 |
BS_Reserved1 | 37 | db | 1 | 未使用 | 0 |
BS_BootSig | 38 | db | 1 | 扩展引导标志 | 29h |
BS_VolID | 39 | dd | 4 | 卷序列号 | 0 |
BS_VolLab | 43 | db | 11 | 卷标,必须是11个字符,不足以空格填充 | |
BS_FileSysType | 54 | db | 8 | 文件系统类型,必须是8个字符,不足填充空格 | FAT12 |
62 |
|
| 引导代码,由偏移0字节处的短跳转而来 | ||
510 | dw | 2 | 系统引导标识 | 0aa55h |
首先是跳转指令,偏移0处的跳转指令必须是合法的可执行的基于x86的CPU指令,如:jmp start,这样可以生成3字节长的指令,(加关键字short的短跳转指令的长度是2字节),指向操作系统引导代码部分。Windows和MS-DOS生成的FAT12启动扇区中的跳转指令是短跳转,如:jmp short start,然后加一个nop的空指令来保持3字节的长度。
逻辑扇区(1-18):
此处存放文件分配表(File Allocation Table)0面0道第2扇区到第10扇区的9个扇区是FAT表的存放位置,为了预防,0面0道的第11扇区到1面0道第1扇区的9个扇区是第2个FAT表的存放位置,这第2个FAT是备用的,当第一个FAT出了问题里,可以用第2个FAT。
FAT12 中,每个文件分配表项只占12位(bit),即1.5字节(byte),每个表项代表一个扇区,在这里,磁盘只有扇区的概念,磁盘里所有扇区都被类似于上一段提到的磁盘读写方式线性地编址(LBA),不再有CHS。这里还要提一提簇的概念:DOS会把2个扇区作为一簇,那么文件就要以簇为单位读写。簇的大小通常根据磁盘的大小设定,以尽可能少浪费磁盘空间为本。
FAT12每个表项的值指出文件存放的下一个扇区号,同时也是表项入口。比如如果文件的存放的第一个扇区是002,那系统首先找FAT的002,在002处得到一个值003,表示文件下一个扇区是003号,再接着003表项找,得到006...,表项的值含义如下:
000 - 此簇未用;FF8 - FFF 该簇为文件的最后一簇;FF0 - FF7,此簇为坏,不可用;其它值表示文件下一簇的簇号。
下面的图来说明FAT的基本原理:
F0 FF FF 03 50 00 F7 1F 01......
用户数据区起始扇区=隐藏扇区+保留扇区+FAT表数*FAT表所占扇区+根目录所占扇区
注意,在FAT12中:0+1+2*9+14=33
簇起始线性扇区=用户数据区起始扇区+(簇号-2)*每簇所占扇区-1
例如:第2号簇的起始线性扇区=33+(2-2)*1-1=32,而第6号簇的起始线性扇区=33+(6-2)*1-1=36
扇区 = (LBA MOD 每道扇区数) + 1
磁道 = (LBA / 每道扇区数) / 磁头数
磁头 = (LBA / 每道扇区数) MOD 磁头数
根据上面的公式,得到以下计算值:
002: S = ( 32 MOD 18 ) + 1 = 15
002: C = ( 32 / 18 ) / 2 = 0
002: H = ( 32 / 18 ) MOD 2 = 1
-----------------
011: S = ( ( 11+31-1) MOD 18) + 1 = 6
011: C = ( ( 11+31-1) / 18) / 2 = 1
011: H = ( ( 11+31-1) / 18) MOD 2 = 0
表项编号 值(16位) 备注
000 | FF0 | <- 000 项 001项为表头,1字节 0xF0表示存储介质
001 | FFF | <- 2、3字节为 0xFFFF ,固定值,FAT标志
002 | 003 | <- 文件下一簇为003
003 | 005 | <- 下一簇:005
004 | FF7 | <- 坏簇,不可用
005 | 011 | <- 下一簇:011
........................................
011 | FF8 | <- 该文件结束
012 | 000 | <- 可用簇
.......................................
根据上表,我们可以知道,一个文件占用了 002,003,005,011 这4个簇。
逻辑扇区(19-32):
此处存放文件目录表(File Directory Table)1面0道的第2扇区起到1面0道的第15扇区(共14个扇区)用于存放 FDT。FDT没有备份,所以没有第二个FDT。这里要注意的是,磁盘为了读写的速度,0面0道的18个扇区接下来的是 1面0道的扇区,而不是0面1道,因为0面0道跟1面0道同在一个柱面上(同心圆),只是用的磁头不同。
每个FDT项占32字节,分配如下:
=======================
0 - 7 : 8字节,文件名
8 - 10: 3字节,文件扩展名
11 :1字节,文件的属性
12 - 15:4字节,保留
16 - 21:6字节,保留
22 - 23:2字节,文件最后修改时间(时分秒,5:6:5)
24 - 25:2字节,文件最后修改日期(年月日,7:4:5,年取0-119对应 1980 - 2099)
26 - 27:2字节,文件首簇号,我们可以根据这个值在FAT中找到文件的存储位置
28 - 31:4字节,文件的长度,以字节为单位
===========================
0 - 7 文件名含义:0 - 目录项为空,可用;E5 - 此文件已经被删除
7 - 10 :文件名和扩展名为8.3格式,如果不够,必需用空格填充,即文件名如果只有6个字节,那剩下的2个字节必须以空格填充。文件名和扩展名都是大写。
11属性字节含义:00 - 普通文件;01 - 只读;02 - 隐藏;04 - 系统文件;10(1x) - 该文件是目录。
逻辑扇区(33-2879):
此处存放文件数据
引用:http://blog.sina.com.cn/s/blog_3edcf6b80100crz1.html