Skip to the content.

本文记录FAT文件系统的学习内容,不是文件系统的详细说明文档。

FAT,File Allocation Table,文件分配表。有FAT12,FAT16和FAT32三种类型,FAT后面的数字指的是每个FAT entry的大小,比如FAT32指的是 FAT entry = 32bit。 FAT文件系统是相对比较古老的文件系统,随着时间的推移,FAT12和FAT16使用已经不多了,现在常见是FAT32。 FAT文件系统与NTFS、ext4、xfs这些文件系统相比,有明显的问题,但是它原理简单,到现在还有很多地方在使用,比如操作系统启动分区(UEFI需要一个FAT32启动分区),一些电视机之类的多媒体设备识别FAT32文件系统等。

上图是FAT文件系统的布局图,其中中间部分的FAT Region就是FAT文件系统的最核心部分:文件分配表。

1. 区域如何分配

布局图中将整个文件系统分成是4个区域:

保留区域的作用很重要,里面保存了整个文件系统的重要信息。 BPB(BIOS Parameter Block),同时也是 Boot Sector 启动扇区,指的都是保留分区中的第一个扇区(sector 0)。 这部分内容类似于其他文件系统说的超级块(super block)。 这部分内容是需要重点关注的,下面列出一些重要的参数:

以上我们可以计算出(只考虑fat32,无RootDir区域):

2. FAT 区域

所以:

# 没有 cluster_id 0 和 1, fat[0]和fat[1]作为标识位用
data[0]  <--> cluster_id=2 <--> fat[2]
data[1]  <--> cluster_id=3 <--> fat[3]
...

3. 目录和文件的存储

数据区存放的就是正儿八经的目录和文件了,那么如何来存放呢? FAT32使用了一个简单的 目录结构(Directory Structure): 大小为32B,内容包括目录名称、目录属性、创建时间等、第一个Cluster、文件大小等基本信息。 注意:文件也用这个目录结构来存放基本信息,区别在于目录属性的不同。另外目录对应的Cluster里面存储的是该目录下边的文件或目录的目录结构(Directory Structure),文件对应的Cluster里面存放的就是真正的文件二进制数据了。

那么第一个文件或者目录的目录结构(Directory Structure)在哪里呢? – BPB扇区中有一个参数BPB_RootClus,保存了FAT32文件系统根目录对应的Cluster ID,一般=2,从这里可以查看到根目录下的目录结构,从而继续搜索下去,就能遍历整个文件系统了。

一张图来看下过程:

4. 其他

感觉有一些细节并没有在参考文件中明确写,下面的FAT32是使用mkfs.fat创建:

# mkfs.fat -v -F 32 -s 8 -S 512 fs.img
# mount fs.img ttt

(1) 如果删除一个文件,会发生什么变化?

我们文件系统中有一个文件aaa/bbb.bmp, aaa目录结构存放位置0x24000,bbb.bmp目录结构存放位置0x25040,bbb.bmp数据存放位置0x26000开始,现在将该文件删除后,只是在长名称和短名称目录结构的0号位置写入0xe5(长名称结构在前,短名称结构在后),其他未改变,并没有将数据进行置0操作。

(2) 再写入另一个文件会怎么样?

可见删除标记的bbb.bmp目录结构已经被覆盖了。

root:aaa# cat /etc/services > cccc.txt
root:aaa# hexdump -C ../../fs.img -s 0x25000 |head
00025000  2e 20 20 20 20 20 20 20  20 20 20 10 00 4f 78 31  |.          ..Ox1|
00025010  9d 55 9d 55 00 00 78 31  9d 55 03 00 00 00 00 00  |.U.U..x1.U......|
00025020  2e 2e 20 20 20 20 20 20  20 20 20 10 00 4f 78 31  |..         ..Ox1|
00025030  9d 55 9d 55 00 00 78 31  9d 55 00 00 00 00 00 00  |.U.U..x1.U......|
00025040  41 63 00 63 00 63 00 63  00 2e 00 0f 00 36 74 00  |Ac.c.c.c.....6t.|
00025050  78 00 74 00 00 00 ff ff  ff ff 00 00 ff ff ff ff  |x.t.............|
00025060  43 43 43 43 20 20 20 20  54 58 54 20 00 57 57 0a  |CCCC    TXT .WW.|
00025070  9e 55 9e 55 00 00 57 0a  9e 55 e2 00 80 38 00 00  |.U.U..W..U...8..|
00025080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

根据参考资料的目录项数据结构内容来分析cccc.txt目录项0x25060,可以得到第一个cluster_id=#226, 地址是0x104000,原有bbb.bmp cluster_id=#3, 数据地址0x26000并没有被覆盖。

(3) 重命名文件会怎样?

root:aaa# mv cccc.txt dddd.txt
root:aaa# hexdump -C ../../fs.img -s 0x25040 |less
root:aaa# hexdump -C ../../fs.img -s 0x25040 |head
00025040  e5 63 00 63 00 63 00 63  00 2e 00 0f 00 36 74 00  |.c.c.c.c.....6t.|
00025050  78 00 74 00 00 00 ff ff  ff ff 00 00 ff ff ff ff  |x.t.............|
00025060  e5 43 43 43 20 20 20 20  54 58 54 20 00 57 57 0a  |.CCC    TXT .WW.|
00025070  9e 55 9e 55 00 00 57 0a  9e 55 e2 00 80 38 00 00  |.U.U..W..U...8..|
00025080  41 64 00 64 00 64 00 64  00 2e 00 0f 00 78 74 00  |Ad.d.d.d.....xt.|
00025090  78 00 74 00 00 00 ff ff  ff ff 00 00 ff ff ff ff  |x.t.............|
000250a0  44 44 44 44 20 20 20 20  54 58 54 20 00 57 57 0a  |DDDD    TXT .WW.|
000250b0  9e 55 9e 55 00 00 57 0a  9e 55 e2 00 80 38 00 00  |.U.U..W..U...8..|
000250c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

可以看到原cccc.txt目录结构(0x25040)0号位被标记删除,并创建新的dddd.txt的目录结构(0x25080),其余均没有变化。

(4)链接操作? 不行。

root:aaa# ln dddd.txt ln.txt
ln: failed to create hard link 'ln.txt' => 'dddd.txt': Operation not permitted
root:aaa# ln -s dddd.txt ln.txt
ln: failed to create symbolic link 'ln.txt': Operation not permitted

参考资料