本文主要是从应用角度出发,分别阐述操作系统接口,计算机语言,文件系统等背后的一些知识,规范,原理,设计思想,应用法门,让初学者编码有一个整体的,全局的认识,有一个物理的视角,找到自己的起点。

文件系统

FAT

FAT是Windows下的一款经典文件系统,当时Windows系统下一定要做两件事情是:碎片整理和杀毒,而这些都同FAT文件系统有关。下面先了解下FAT系统的基本内容,下图是FAT的“物理视图”。

    

BPB (启动引导区域)-- 相当于FAT文件系统的“头部”,定以了FAT文件系统的“元数据”:扇区大小,簇的大小,FAT表的位置和大小,根目录的位置,基本上FAT文件系统的物理布局,都定义在这个里面,在系统格式化的时候生成。

FAT--全称是File Allocation Table(文件分配表),实质上就是一个大数组,以“簇”为单位 ,来记录硬盘空间的使用情况:

  • FAT12,每个FAT表项是12 bits (1.5个字节)。
  • FAT16,每个FAT表项是16 bits (2个字节)。
  • FAT32,每个FAT表项是32 bits (4个字节)。
FAT 说明
    FAT12        FAT16    FAT32  
0x000 0x0000 0x0000 “簇”未分配
2 .. max 该文件下一个“簇”号
max +1 .. 0xFFE 预留
0xFFF 0xFFFF 0xFFFFFF “簇”的结束标志

目录结构--目录也被当作(抽象)成一种文件,它的内容就是一个目录表。目录项的定义如下:

字段名   offset       size     描述
DIR_name 0 11 文件名
...      
DIR_FstClusHI 20 2

数据簇地址的高地址

...      
DIR_FstClusLO 26 2 数据簇地址的低地址
DIR_FileSize 28 4 文件大小
  • DIR_name: 长度只有11个字节--这是DOS时代“经典”的文件名过长的原因,FAT32通过“长文件名”扩展解决了这个问题。
  • DIR_FstClus(HI/LO): 数据的起始地址,再通过FAT表去查找后续的地址。
  • DIR_FileSize: 文件大小, 4G的文件大小限制就是从这里来的--因为它的长度只有4个字节。

下面我们以一个只有10M的FAT16文件系统为例,来实际说明一下FAT文件系统的工作过程。首先,解析BPB区域, 得到FAT16的“元数据”,部分重要信息如下:

 

根据上面信息,可以画出FAT16物理布局图,

    

因为根目录是特殊的数据,也可以说数据区是从0x9200开始的。

 

读取根目录

接下来找到根目录,读取它的目录表:

 

根据目录项的定义,得到根目录内容如下:

文件名 起始地址(单位是“簇”) 类型
ROOT_F~1.IMG 0x03 文件
HOME 0x0d 目录
  • ROOT_F~1: “~1”表明文件名过长被截了。
  • 起始地址: 第一个目录项的'DIR_FstClusLO'(0x523A)开始的2个字节是0300,由于是低字节在前(little endian),所以地址是0x03,而不是0x0300。同理,第二个目录项目的地址是0x0d。

计算文件起始位置

文件地址的物理簇号是从2开始算起的,因此,ROOT_F~1.IMG的起始物理地址(以字节为单位)计算如下:

文件起始地址:  0x9200 + (3 - 2) * 2048 = 0x9A00。

  • 0x9200是根目录除外的数据区域起始地址。
  • 2048是每一个簇的大小。

0x9A00就是文件的起始地址,当我们读完该簇后,该如何去寻找下一个簇呢?

查找FAT表 

(FAT)

因为FAT16是的FAT表项是2个字节,因此 FAT[3]是0x04, 也就是说下一个文件簇的位置是4, 完整的查找过程如下:

  • FAT[4] == 5
  • FAT[5] == 6
  • ...
  • FAT[11] == 12(0c)
  • FAT[12] == 0xFFFF (文件结束符)。

可以看出 FAT就是一个链接,当前的值指向下一个簇号,直到以0xFFFF作为结束。

同理读取目录也是一样的,本例中,HOME目录的起始地址是:  0x9200 + (0x0d - 2) * 2048 = 0xEA00

  

0xea00的内容同根目录一样,就是该目录下的目录表,如果该目录的内容超过一个簇,也同样去通过FAT表去查找其它的内容。

这就是FAT文件系统的基本概念和工作流程。不难看出FAT采用的这种链表结构,会导致碎片化会很严重,使用时间长了以后,一个文件的簇链得到处都是。另外,FAT还没有权限管理,病毒程序就如入无人之境,可以随意复制和破坏。FAT的好处是简单灵活,文件的个数不固定,且占用磁盘空间少。但是,毕竟适应不了目前大容量高性能的要求,微软从FAT12打补丁到FAT32后,就推出了NTFS文件系统。

后记

到这里,文件系统的一些基础知识就介绍完了,那么了解它有哪些实际的意义呢?
首先,像电影里面的黑客,可以直接面对文件系统的原始数据,比如:从文件系统损坏的硬盘里面恢复一些关键文件--通过读取磁盘文件系统的元数据,比如说直接找目录表,看看哪些文件还可以被识别,再查找相应的Inode节点(或FAT表),读取它的BLOCKS(或簇),只要物理上还没损坏,就能恢复出来。

其次,可以做一些磁盘类的工具,像文件搜索,恢复删除文件之类--文件被删除后,文件系统一般都是修改了些标志位,如:bitmap的空闲标志置1,表示空间被释放等,其实文件的内容还在硬盘上,只要及时地找到文件的位置,就有恢复的可能。我曾经用python做过一个小工具,可以浏览,提取iso 9600文件系统(光盘)里的文件,这样可以在不使用虚拟光驱的情况下,把iso镜像文件的内容都提取出来。

 

参考书籍

  1. ELF Format (Portable Formats Specification)

  2. libc (The GNU C Library Reference Manual)

  3. https://en.cppreference.com/w/

  4. ext2 (The Second Extended File System Internal Layout)

  5. Microsoft FAT Specification

用户评论:
发表评论: (限500字)

注册 忘记密码 登录