汪道之

有人的地方就有江湖

0%

病毒-基础-文件系统

初识文件系统

文件系统就是组织文件的一种方式
文件管理包括文件生成、删除、目录查询等
eg:

  1. Windows文件系统:FAT12、FAT16、FAT32、NTFS
  2. Linux文件系统:EXT2

FAT12文件系统的磁盘格式

  1. 引导扇区(DBR):记录各种参数,比如扇区大小,一簇的扇区数
  2. 文件分配表(FAT):记录已分配的扇区和可用扇区
  3. 文件目录表(DIR):记录根目录文件项的表,文件项包括文件,目录。
  4. 用户数据:存放数据的区域

image-20210425164158141

注:左侧为扇区号、第二个FAT12为备用FAT

如何定位到一个文件

FAT表的格式

在文件系统中,文件分配的最小单位是簇,哪怕只有一个字节也会分配一簇
簇是由n个扇区组成
其中n在引导扇区的引导记录中定义

image-20210428094415697

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]元素,如下图:

image-20210428095326854

真正在FAT12表中的查找方法:

image-20210428095655541

注意:三个字节中如何分配的两个半字节,可以结合小端机中数据的存放规则记忆

遍历一个文件占用的簇

image-20210428100002898

如何获取首簇号

根目录区有根目录表,其记录了文件的各种信息。
根目录表中包含多条记录,每条记录占32个字节

现在我们关注根目录表中的文件名字段和首簇号字段
文件名

在记录首部偏移0开始,共11字节,前8个字节记录文件名,后3个字节记录扩展名(中间的.不需要记录)名字的结束以空格表示(即0x20)

首簇号

首簇号首部偏移0x1A开始,共2个字节

下图是getexe.com的文件名与首簇号图示,getexe只占用6个字节,后两个字节用空格填充,首簇号是0003

image-20210428160041729

如何查找根目录
  1. 从磁盘0头0道1扇区读出引导区(Boot)512字节,从其中引导记录获取相关信息:Boot区占用扇区数,FAT表数目,每个FAT表的扇区数,1个扇区的字节数
  2. 计算根目录区的起始位置为:
    [ 1(Boot区扇区数)+2(FAT数目)*9(FAT扇区数)] * 512 = 0x2600
    即2600h为根目录区起始位置
  3. 从引导记录获取根区记录数,缺省224条,按每条记录32字节读出所有记录
  4. 每条记录开始11个字节为文件名,比较文件名匹配则找到记录,从首簇字段(从该记录开始偏移1Ah处)获得首簇号
多级目录的查找流程

以查找a:\tem\tem.txt为例

大致思想:

在根目录区下的tem项,会给出tem项的首簇号,系统就可以通过FAT表在数据区找到tem对应的信息(即tem目录表),在这个tem目录表下,再通过该目录表的项(每项32字节),继续查找tem下的文件或更下层的目录,如此,即可形成多层次的目录嵌套

详细流程:

image-20210428161152854

总结
  1. 根据文件路径第一项先查看根目录表,是否有匹配的项,如果有,通过对应项的首簇段获取该子目录表的首簇号
  2. 通过首簇号和FAT表获得子目录表的全部内容,根据文件路径的第二项,遍历子目录表,一次偏移32字节用名字匹配的方法查找记录项,如果找到则重复1、2步查找下一项,找不到则结束
  3. 如果找到了最后一层目录表(路径的倒数第二项,最后一项是文件名),在其中找到了被查文件的项,从中获取首簇号,即可通过FAT表访问整个文件簇

如何删除文件

只要使目录文件中的记录项无效就可以了,实际目录项的第一个字节被修改成了E5,而对于FAT表中的簇,我们只要把簇链的每一项复原成00就可以了

也就是说,删除文件其实只修改了目录文件和FAT表,实际的文件扇区并没有修改

如何恢复文件

在目录表中查找E5+后续文件名,根据偏移关系找到首簇号,对于只有一个簇的文件恢复简单,将目录表和FAT表中的值更改即可,可是簇链消失了,对于占用多个簇的文件恢复较为复杂,需要遍历数据区,匹配文件标识等恢复簇链

如何创建文件

  1. 首先定位到文件所在的目录文件,然后查找目录项,如果第一个字节为00或E5表示可用
  2. 根据文件大小计算簇数目,然后在FAT表首部(簇2)开始查找值为00的项,将其簇号写入第一步找到的目录项的首簇号字段
  3. 继续在FAT表中找00的项,将簇号写入前一步找到的项中以形成簇链,最后一个簇写入FFF
  4. 填写文件目录项的创建时间,属性,大小的字段

FAT16和FAT32文件系统

FAT16:

  1. FAT表项为16bits(2字节)
  2. 最大簇号0xFFFF,就是65535
  3. 一簇为32k
  4. 最多管理32k*65535=2GB的分区

FAT32:

  1. FAT表项为32bits(4字节)
  2. 取消了根目录区,而是在引导记录中存放指向根目录区的首簇字段,一般为簇2,
  3. 支持长名文件,由扩展的32字节记录项构成
  4. 首簇号由2个字段构成,分别代表高位两字节和低位两字节
  5. 引导区有保留区