初识文件系统
文件系统就是组织文件的一种方式
文件管理包括文件生成、删除、目录查询等
eg:
- Windows文件系统:FAT12、FAT16、FAT32、NTFS
- Linux文件系统:EXT2
FAT12文件系统的磁盘格式
- 引导扇区(DBR):记录各种参数,比如扇区大小,一簇的扇区数
- 文件分配表(FAT):记录已分配的扇区和可用扇区
- 文件目录表(DIR):记录根目录文件项的表,文件项包括文件,目录。
- 用户数据:存放数据的区域
注:左侧为扇区号、第二个FAT12为备用FAT
如何定位到一个文件
FAT表的格式
在文件系统中,文件分配的最小单位是簇,哪怕只有一个字节也会分配一簇
簇是由n个扇区组成
其中n在引导扇区的引导记录中定义
FAT表的本质
FAT表的本质是磁盘簇分配情况的数据表示
在FAT12文件系统中,FAT表以3个半字节(3*0.5Byte=1.5Byte=12bit)来记录一个簇的相关情况,这也是FAT12中12的由来
FAT表中每3个半字节为一个元素,这个元素就代表一个簇,簇号从0开始,这个元素中存放的整数值表示其链接的下一簇的簇号
FAT表的查找与遍历机制
FAT表是一个数组,数组中每个元素是1.5字节的整数,为了查找FAT表中簇号为N的元素,只需用N作索引查找FAT[N]元素,如下图:
真正在FAT12表中的查找方法:
注意:三个字节中如何分配的两个半字节,可以结合小端机中数据的存放规则记忆
遍历一个文件占用的簇
如何获取首簇号
根目录区有根目录表,其记录了文件的各种信息。
根目录表中包含多条记录,每条记录占32个字节
现在我们关注根目录表中的文件名字段和首簇号字段
文件名
在记录首部偏移0开始,共11字节,前8个字节记录文件名,后3个字节记录扩展名(中间的.不需要记录)名字的结束以空格表示(即0x20)
首簇号
首簇号首部偏移0x1A开始,共2个字节
下图是getexe.com的文件名与首簇号图示,getexe只占用6个字节,后两个字节用空格填充,首簇号是0003
如何查找根目录
- 从磁盘0头0道1扇区读出引导区(Boot)512字节,从其中引导记录获取相关信息:Boot区占用扇区数,FAT表数目,每个FAT表的扇区数,1个扇区的字节数
- 计算根目录区的起始位置为:
[ 1(Boot区扇区数)+2(FAT数目)*9(FAT扇区数)] * 512 = 0x2600
即2600h为根目录区起始位置 - 从引导记录获取根区记录数,缺省224条,按每条记录32字节读出所有记录
- 每条记录开始11个字节为文件名,比较文件名匹配则找到记录,从首簇字段(从该记录开始偏移1Ah处)获得首簇号
多级目录的查找流程
以查找a:\tem\tem.txt为例
大致思想:
在根目录区下的tem项,会给出tem项的首簇号,系统就可以通过FAT表在数据区找到tem对应的信息(即tem目录表),在这个tem目录表下,再通过该目录表的项(每项32字节),继续查找tem下的文件或更下层的目录,如此,即可形成多层次的目录嵌套
详细流程:
总结
- 根据文件路径第一项先查看根目录表,是否有匹配的项,如果有,通过对应项的首簇段获取该子目录表的首簇号
- 通过首簇号和FAT表获得子目录表的全部内容,根据文件路径的第二项,遍历子目录表,一次偏移32字节用名字匹配的方法查找记录项,如果找到则重复1、2步查找下一项,找不到则结束
- 如果找到了最后一层目录表(路径的倒数第二项,最后一项是文件名),在其中找到了被查文件的项,从中获取首簇号,即可通过FAT表访问整个文件簇
如何删除文件
只要使目录文件中的记录项无效就可以了,实际目录项的第一个字节被修改成了E5
,而对于FAT表中的簇,我们只要把簇链的每一项复原成00
就可以了
也就是说,删除文件其实只修改了目录文件和FAT表,实际的文件扇区并没有修改
如何恢复文件
在目录表中查找E5+后续文件名
,根据偏移关系找到首簇号,对于只有一个簇的文件恢复简单,将目录表和FAT表中的值更改即可,可是簇链消失了,对于占用多个簇的文件恢复较为复杂,需要遍历数据区,匹配文件标识等恢复簇链
如何创建文件
- 首先定位到文件所在的目录文件,然后查找目录项,如果第一个字节为00或E5表示可用
- 根据文件大小计算簇数目,然后在FAT表首部(簇2)开始查找值为00的项,将其簇号写入第一步找到的目录项的首簇号字段
- 继续在FAT表中找00的项,将簇号写入前一步找到的项中以形成簇链,最后一个簇写入FFF
- 填写文件目录项的创建时间,属性,大小的字段
FAT16和FAT32文件系统
FAT16:
- FAT表项为16bits(2字节)
- 最大簇号0xFFFF,就是65535
- 一簇为32k
- 最多管理32k*65535=2GB的分区
FAT32:
- FAT表项为32bits(4字节)
- 取消了根目录区,而是在引导记录中存放指向根目录区的首簇字段,一般为簇2,
- 支持长名文件,由扩展的32字节记录项构成
- 首簇号由2个字段构成,分别代表高位两字节和低位两字节
- 引导区有保留区