FAT32文件系统详细解析
date
Aug 30, 2024
slug
2024-08-30-FAT32-file-system-summary
status
Published
tags
文件系统
type
Post
AI summary
FAT32文件系统由微软开发,主要用于小容量存储介质。其基本概念包括簇、文件分配表和目录项,簇是文件存储的基本单位,文件分配表记录文件的簇链和分配状态,目录项描述文件和目录的结构。FAT32的存储结构分为保留扇区、FAT区和数据区,保留扇区包含引导扇区DBR,FAT区有FAT1和FAT2的备份,数据区则用于保存用户数据。
summary
本文对FAT32文件系统的结构进行详细解析,整理了与该文件系统相关的一些核心概念,在此基础上理解整个文件系统的存储结构以及增删操作的逻辑,对FAT32文件系统如何保存数据可以建立一个更为宏观的认识,指导后续工作中存在的与FAT32文件系统相关问题的解决。
FAT(File Allocation Table)文件系统由微软发明并持有部分专利,主要有FAT12,FAT16,FAT32,exFAT四个版本。其中FAT12和FAT16早已淡出人们的视线,FAT32在一些小容量的SD卡里面仍然能够看到,而exFAT则是微软为闪存类型的存储介质定制的FAT类文件系统,因此在U盘、SD卡甚至固态硬盘领域仍然有很大比例的使用。
FAT文件系统的一些基本概念
簇
FAT文件系统以簇(Cluster)为单位对文件所占据的硬盘空间进行分配。一个文件占据的硬盘存储空间总是一个或者多个簇,也就是说每个文件占用的硬盘空间大小是簇大小的整数倍。
FAT32文件系统默认情况下,一个簇的大小为4KB。
在FAT文件系统中,数据区中所有的簇都从2开始编号,每个簇都有一个自己的地址编号。默认情况下,文件系统的根目录就保存在2号簇中。
当文件占据的硬盘空间包含多个簇时,多个簇通过文件分配表中保存的簇信息记录形成一个簇链,因此一个文件所包含的多个簇在物理空间上并不需要是连续的。
文件分配表
文件分配表是FAT文件系统中最重要的数据结构之一。FAT实际上就是文件分配表(File Allocation Table)的英文简称。
FAT文件系统中各个文件和目录的具体内容保存在数据区域的簇中。如果一个文件所占的空间大于一个簇的大小(即4KB),则进一步通过文件分配表结构来描述如何找到后续的簇:即利用文件分配表可以找到每个文件在簇中保存所形成的簇链。目录项中记录了这个文件起始簇的编号,文件分配表中则以簇编号为索引标记同一个文件下一个簇的编号,如果当前簇是该文件的唯一或者最后一个簇,那么在这个簇编号上标记为EOF即可。因此,文件分配表中对于每个簇的标记,不仅包含了各个文件的簇链信息,还标记了这个簇的分配状态。
文件分配表中的所有FAT表项保存在FAT文件系统的FAT区中。在这个FAT区域中,针对数据区的每个簇都保存了一条FAT表项(即数据区中所有簇的分配状态信息记录),每个FAT表项实际上是一条32位长度的记录,从0号簇开始进行编号,其中0号和1号簇被系统保留用于保存特殊标志信息,不是有效的簇,2号簇是数据区第一个簇,以此类推,数据区有多少个簇,在FAT表中就有多少项FAT表项记录与之对应。
- 文件系统被格式化的情况下,整个FAT表会被初始化,此时0号FAT表项会被固定写入0xF8FFFF0F,1号FAT表项正常情况下会被写入0xFFFFFFFF或者0xFFFFFF0F,2号簇因为用于保存文件系统的空的根目录,所以2号簇会被标记为已占用+结束状态标记(0x0FFFFFFF),其他所有簇的FAT表项全部为未占用状态(此时这个簇对应的FAT表项使用全0填充)。
- 当文件系统中一个簇未被占用的情况下,其对应的FAT表项记录使用全0填充。
- 当文件系统中一个簇被占用,并且这个簇是整个文件所占用的簇链的最后一个簇的情况下,这个簇对应的FAT表项会被写入结束标记0x0FFFFFFF。
- 当文件系统中一个簇被占用,并且这个簇不是文件簇链的最后一个簇的情况下,这个簇对应的FAT表项会被写入簇链中下一个簇的编号。
- 如果某个簇存在坏扇区或者处于不可用的状态下,这个簇的FAT表象会被写入0xFFFFFFF7。
目录项
目录项是FAT文件系统中一个重要的数据结构,用于描述整个系统中的目录结构和其包含的文件之间如何归属,以及各个文件和目录在数据区所占空间的起始簇的编号。
FAT文件系统中所保存的每一个文件和目录都对应一个目录项,在这个目录项保存有文件和目录的名称、大小、文件内容所保存的起始簇编号(仅包含起始簇的编号,后续簇的编号结构在文件分配表中的簇链进行检索)以及其他的元数据信息等。因此对于FAT文件系统中的每一个文件的访问,都先要到目录项这个数据结构中找到与之对应的记录,从其中解析出来这个文件的各种元信息数据以及在文件系统中所保存的起始簇编号,再从文件分配表FAT中查找到与之对应的簇链,从而找到该文件所包含的完整数据信息。
目录项又可以分为短文件名目录项和长文件名目录项。在FAT32之前的FAT文件系统中,文件和目录对应的目录项只有短文件名目录项,每个文件和目录对应的目录项的数据结构固定为32个字节,此时文件名的命名规则为标准的8.3结构,即文件名长度最长为8个字符,扩展名最长3个字符。32个字节的短文件名目录项的结构如下:
- 短文件名目录项结构中所包含的信息主要就是:文件名、扩展名,创建/修改/最后访问的日期时间,该文件的长度以及在数据区保存的起始簇的编号等信息。
但是,以上的短文件名目录项只能支持8.3文件名结构,无法支持长文件名。为了解决这个问题,FAT32文件系统中导入了长文件名目录项对其进行支持。因此在FAT32文件系统中,无论文件名的长短是否超过8个字符,每个文件和目录的目录项结构中都包含长文件名目录项LFN和短文件名目录项SFN两个部分,长文件名目录项占据1个或者多个32字节长度,只包含文件的名字,根据文件名的实际长短决定占据1个或者多个32字节长度;短文件名目录项仍然占据固定的32字节长度,仍然是按照上表的结构包含有文件的时间、大小、起始簇编号等信息。
- 文件系统的完整目录项结构保存在数据区中。
DOS引导扇区DBR
FAT文件系统的一开头是整个系统的保留扇区部分(FAT32的保留扇区一般包含有32个扇区),而保留扇区区域的第一个扇区则是DOS引导扇区DBR。这个DBR的数据结构中保存了这个FAT文件系统的各种结构型信息,例如文件系统大小、位置、文件分配表的记录个数和大小等。
DBR扇区的结构如图所示:
- 0x00-0x02的前三个字节是一条可执行的CPU跳转指令,该指令负责跳转到后面从0x5A开始的OS引导程序代码部分,启动操作系统。
- 0x03-0x0A之间的8个字节是OEM字符串,一般是格式化该文件系统所使用的操作系统及其版本号,例如上图中的MSWIN4.1
- 0x0B开始的53个字节是BPB,其后从0x40开始的26个字节是扩展BPB,共计79个字节,用于保存这个文件系统的参数信息。
- 0x5A开始的420个字节是OS引导程序的代码,当然如果这个文件系统分区没有安装操作系统的话,是不可能运行这段代码的。
- 最后的0x55和0xFF是结束标志。
对于没有安装操作系统的文件系统而言,DBR中所包含的BPB结构无疑是最重要的信息结构,其详细定义如下图所示:
- 可以看到,BPB结构中包含了这个文件系统每个扇区的字节数,一个簇所包含的扇区数(即簇的大小),FAT表项的个数(即文件系统中所包含的簇的数量),文件系统的大小,根目录的起始簇号(一般是2)等。因此基本上BPB就定义了整个FAT文件系统的完整结构划分的情况。
FAT32文件系统的存储结构
FAT32文件系统从总体上可以分为3个部分:保留扇区(包含其起始扇区的DBR),FAT区,数据区。
保留扇区
如上图所示,保留扇区部分包含有32个扇区,第一个扇区是FAT文件系统的引导扇区DBR,后续的31个扇区是其余保留扇区部分。
保留扇区的32个扇区中,除了第一个扇区用于保存引导扇区DBR以外,还有个别扇区用于存储较老版本的Windows操作系统的OS引导代码的扩展部分,其他扇区都是没有用到的。
DBR扇区的细节在前面已经详细描述,不再赘述。
FAT1和FAT2
FAT区域紧跟在保留扇区之后,包含有两个独立的部分:FAT1和FAT2,其中FAT2是FAT1的备份,防止因为FAT1损坏的情况下整个文件系统损坏,因此FAT1和FAT2的内容通常是完全相同的。
如前所述,FAT这个数据结构的主要作用就是两个:记录各个目录和文件所占用的下一个簇的编号,从而形成簇链;以及标记各个簇的分配状态,已分配还是未分配。
FAT表格实际上就是对数据区中所包含的所有簇的分配状态和簇链结构进行跟踪和管理。
因为每个FAT表项的大小固定是32位,而数据区的簇的数量也是固定的,因此FAT区域的大小也就固定了。
数据区
紧跟在FAT区域之后的就是FAT32的数据区,这部分是真正用于保存用户数据的区域,文件系统里面目录和文件的内容都保存在数据区。如前所述,数据区按照簇为单位进行划分,每个文件或者目录的内容占用其中一个或者多个簇的存储空间。
需要注意,簇的编号是从2开始编号的,也就是说数据区第一个簇的编号就是2号。一般情况下,数据区的2号簇用于保存这个文件系统的根目录,文件系统中的所有其他目录和文件都在这个根目录下保存。
FAT32文件系统中的增删操作
FAT文件系统的格式化
当对硬盘的分区进行FAT文件系统的格式化操作后
- FAT区:这个文件系统的FAT区域中所有的FAT表项会被全部清空,0号和1号簇对应的FAT表项会被设置固定值,2号簇(用于保存文件系统的根目录)对应的FAT表项设置为已占用状态,其他所有的簇对应的FAT表项全部为未占用状态。
- 数据区:格式化后数据区的所有数据全部被格式化,整个数据区安装BPB结构中指定的簇大小进行划分,除了位于数据区开头的2号簇用于保存文件系统的根目录以外,其他簇全部为未占用状态。
FAT32文件系统中目录和文件的新增操作
当在FAT32文件系统中新建目录和文件时,会首先在其父目录所在的簇中增加一个目录项结构(长文件名目录项+短文件名目录项),在其中设定文件/目录的名称、创建/修改时间、文件大小等,以及对这个新建的文件/目录分配一个未被占用的簇,把起始簇的编号写入其目录项结构;然后把这个簇对应的FAT表项设置为占用状态,并把新建文件和目录的内容写入数据区的这个簇中。
如果这个新建的目录和文件所占用的硬盘空间超过一个簇的大小,则需要在其FAT表项中写入下一个簇的编号,从而形成一个簇链用于保存完整的文件和目录。
FAT32文件系统中目录和文件的删除操作
对于文件和目录的删除操作与新建的流程类似,首先在数据区中找到要删除的文件和目录的目录项(在其父目录的簇中保存),从其中得到这个文件和目录的起始簇编号,然后在FAT表中删除这个文件和目录对应的簇链,把其对应的所有簇的FAT表项全部标记为未分配状态;然后从其父目录的簇中删除其目录项结构。
如果要删除的目录中包含有其他子目录和文件的话稍微复杂一些,不同同样是递归循环找到其包含的所有文件和叶子目录,全部删除后再逐级向上删除其父目录。
参考文档
- 《固态存储:原理、架构与网络安全》 夏鲁宁,贾世杰,陈波 2.1 FAT