【问题标题】:FAT32 File Allocation Table size on Windows 7 formatted drive is out of FAT32 specificationWindows 7 格式化驱动器上的 FAT32 文件分配表大小超出 FAT32 规范
【发布时间】:2016-12-17 00:31:36
【问题描述】:

我正在编写一个嵌入式 FAT32 驱动程序。我有问题。

我用零填充我的金士顿 DTR30G2 高达 1GB 并将其插入 Windows 7 盒子,并将其格式化为 FAT32。然后,在我的 Linux 机器上,我将 1GB 的闪存转储到文件中并在十六进制编辑器中打开它并获得以下值:

uint16_t BPB_ResvdSecCnt = 32 at offset 0xE
uint8_t BPB_SecPerClus = 8 at offset 0xD
uint8_t BPB_NumFATs = 2 at offset 0x10

接下来,我看一下FAT32卷ID中的扇区总数:

uint32_t DskSize = 30734336 at offset 0x20

同Linux报告:

thinkpad :: ~ % cat /sys/block/sdb/sdb1/size                                      
30734336

这一切都在 FAT32 的规范内。现在,让我们看看偏移量 0x24 处驱动器上的 FAT 表扇区大小。这是29951 部门。这不在 FAT32 的规范中。微软官方文档声明了以下等式:

RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;
TmpVal1 = DskSize – (BPB_ResvdSecCnt + RootDirSectors);
TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;

其中RootDirSectors 对于 FAT32 始终为 0,因为它在 FAT32 文档中指定:

请注意,在 FAT32 卷上,BPB_RootEntCnt 值始终为 0,因此在 FAT32 卷上 RootDirSectors 始终为 0。

所以这给出了:

TmpVal1 = DskSize – BPB_ResvdSecCnt;
TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;

现在,我实现了这个:

int main(void) {

  uint32_t DskSize = 30734336;
  uint32_t FATSz;
  uint16_t BPB_ResvdSecCnt = 32;
  uint8_t BPB_SecPerClus = 8;
  uint8_t BPB_NumFATs = 2;
  uint32_t RootDirSectors = 0;

  uint32_t TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
  uint32_t TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
  TmpVal2 = TmpVal2 / 2;
  FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;

  printf("%d\n", FATSz);

}

此代码 sn-p 将29985 扇区作为 FAT 大小。

编辑:

mkfs.fat 3.0.28 在 Linux 上,当与以下设置一起使用时:

mkfs.fat /dev/sdb1 -S 512 -s 8 -F 32 

给出29956 的FAT 表大小。现在,我在同一个分区上有 3 个不同数量的同一个文件系统。

  • FAT32 规范:29985
  • Windows 7:29951
  • mkfs.fat: 29956

我现在应该信任谁? 规范实现。为什么34 扇区的数字不同?

【问题讨论】:

    标签: windows fat32


    【解决方案1】:

    我找到了一份您似乎在询问的关于 here 的规范副本 (PDF)。

    您所指的文档部分(在第 21 页的顶部)是建议,不是强制性的 - 它描述了某些未指定版本的 Windows 在计算 FAT 大小时所做的事情格式化 FAT32 卷。唯一实际的要求FATSz 足够大以包含FAT。该文档明确允许使用对于 FAT 来说太大的FATSz,并要求在格式化期间将浪费的扇区归零,否则将被忽略。

    根据您的观察,似乎在现代版本的 Windows 中使用了一种更有效的算法。 (似乎链接的文档在说明它所描述的算法永远不会导致超过 8 个浪费的扇区时是不正确的。我没有尝试进行数学计算,但也许这与您的体积有关'正在分析使用 4KB 集群,而不是文档为 14GB 磁盘指示的 8KB 集群 - 请参见第 20 页上的表格。)

    如果您正在格式化磁盘,您要么需要使用文档中的算法,要么非常仔细地编写自己的算法,确保它永远不会产生太小的结果。 (或者,如果碰巧您已经知道磁盘的大小,则可以使用 Windows 在格式化相同大小的磁盘时使用的参数。)

    如果你挂载的是一个已经格式化的磁盘,你当然会使用存储在磁盘上的值。

    【讨论】:

    • 顺便说一下,除非我忽略了某些东西,否则实现一个非常简单的算法应该很简单,它总是会产生最佳答案:首先假设您必须支持尽可能多的集群整个磁盘,并计算出它的 FAT 大小。这给了你一个最大值。然后将该大小减少一个扇区,在此基础上计算磁盘上可以容纳多少实际群集,并查看它是否仍然适合。冲洗并重复。这听起来效率低下,但实际上不会花费很长时间,而且您也不会经常格式化磁盘。
    • 我真的不喜欢FAT32规范松散的样子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多