FAT表记录了磁盘数据文件的存储链表,对于数据的读取而言是极其重要的,以至于Microsoft为其开发的FAT文件系统中的FAT表创建了一份备份,就是我们看到的FAT2。

    FAT2 与 FAT1 的内容通常是即时同步的,也就是说如果通过正常的系统读写对FAT1 做了更改,那么FAT2 也同样被更新。

    FAT表工作的原理:当存储一个大的文件时,会以簇为单位拆分成多个簇存放在磁盘,它们的存放的簇号并不一定是连续的,所以这里用到了FAT表,将该文件所用到的簇号串联起来。

    例如截图如下,绿色的部分为存储文件的数据,FAT表查询顺序如下:

    1. 先从根目录(Root folder)找到该文件的起始簇号 12,并且读取簇号 12 地址的文件数据。
    2. 从FAT表中,找到簇号12存放的下一个簇号为13,并且读取簇号 13地址的文件数据。以此类推到簇号65。
    3. 从FAT表中,找到簇号65存放的下一个簇号为87,并且读取簇号 87地址的文件数据。下一次FAT表查询直接从簇号65跳转到簇号 87。
    4. 经过上面的连续查询FAT,直到读取FF标记,代表文件读取完成。

      6.FAT32 FAT表 - 图1

    NOTE:
    以上的分析只是理论上的,和实际使用有一些差异。后面会以实际的例子来介绍FAT表整个的工作过程。

    下面通过实例根目录(Root folder)文件:stm32f4xx_gpio.c来介绍FAT表的使用:

    6.FAT32 FAT表 - 图2

    通过上面实例表格了解到重要信息总结如下:

    • 文件起始簇号
      文件起始簇号为0x0000 000C,说明该文件的起始地址为:
      文件地址 = 根目录开始地址 + ((起始簇号 - 根目录簇号(Root Cluster Number)) * 每簇扇区数(Sectors Per Cluster) * 扇区字节数(Bytes Per Sector))
      文件地址 = 0x1000000 + ((0x0C - 2) * 32 * 512) = 0x1028000 Bytes
      经过计算可以得到文件起始存放位置在0x1028000,然后验证果然在该位置找到了文件:stm32f4xx_gpio.c存放的数据,如下:

      6.FAT32 FAT表 - 图3

    • 文件大小
      文件大小为0x0000 6011(24593),在下面的文件属性截图可以查看到文件大小确实为24593字节。
      ???为什么占用磁盘空间为32768字节????
      因为系统读写磁盘的单位为簇为单位,存放数据不满足一个簇时也将占用这整个簇(其它文件也无法使用该簇多余的空间),所以这里占用空间32768字节 = 2簇 * 32 * 512 字节 = 32768字节这样计算得来。

      6.FAT32 FAT表 - 图4


      读取完文件起始簇号存放的文件数据后,就查询下一个簇号存放数据。 FAT表以簇为单位,标识分区中空间的使用情况(每个标识占4字节)。FAT前2簇为保留簇(簇0和簇1),不分配给文件使用,其内容含义如下所示:

      FAT16:F8 FF FF FF
      FAT32:F8 FF FF 0F FF FF FF FF

      一个FAT表项值表明了文件占用的一个簇号并指明下一簇号的位置,说明读取完簇号0x0C(12)后读下一个簇号0x0D(13),其示意图如下图所示:

      6.FAT32 FAT表 - 图5

    FAT表按顺序依次记录了该盘各簇的使用情况,是一种位示图法。每簇的使用情况用32位二进制填写,未被分配的簇相应位置写零;坏簇相应位置填入特定值;已分配的簇相应位置填入非零值,具体为:如果该簇是文件的最后一簇,填入的值为FFFFFF0FH(即0x0FFFFFFF),如果该簇不是文件的最后一簇,填入的值为该文件占用的下一个簇的簇号,这样,正好将文件占用的各簇构成一个簇链,保存在FAT表中。0000000H、00000001H两簇号不使用,其对应的两个DWORD位置(FAT表开头的8个字节)用来存放该盘介质类型编号。

    FAT表的大小就由该逻辑盘数据区共有多少簇所决定,取整数个扇区。

    当文件系统被创建,也就是进行格式化操作时,分配给FAT区域的空间将会被清空,在FAT1与FAT2的0号表项与1号表项写入特定值。由于创建文件系统的同时也会创建根目录,也就是为根目录分配了一个簇空间,通常为2号簇,所以2号簇所对应的2号FAT表项也会被写入一个结束标记,如上图所示。

    如果某个簇存在坏扇区,则整个簇会用FAT表项值0xFFFFFF7标记为坏簇,不再使用,这个坏簇标记就记录在它所对应的FAT表项中。

    在文件系统中新建文件时,如果新建的文件只占用一个簇,为其分配的簇对应的FAT表项将会写入结束标记。如果新建的文件不只占用一个簇,则在其所占用的每个簇对应的FAT表项中写入为其分配的下一簇的簇号,在最后一个簇对应的FAT表象中写入结束标记。

    新建目录时,只为其分配一个簇的空间,对应的FAT表项中写入结束标记。当目录增大超出一个簇的大小时,将会在空闲空间中继续为其分配一个簇,并在FAT表中为其建立FAT表链以描述它所占用的簇情况。

    对文件或目录进行操作时,他们所对应的FAT表项将会被清空,设置为0以表示其所对应的簇处于未分配状态。