FAT32文件分配Windows 7格式化驱动器上的表大小超出FAT32规范

时间:2016-08-10 14:39:47

标签: windows fat32

我正在编写嵌入式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的规格。 Microsoft官方文档声明了以下等式:

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;

对于FAT32,RootDirSectors始终为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);

}

此代码段提供29985个扇区作为FAT大小。

编辑:

Linux上的

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

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

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

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

我现在应该信任谁? 规范实施。为什么数字会被34个部门关闭?

1 个答案:

答案 0 :(得分:2)

我找到了您似乎询问here(PDF)的规范的副本。

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

根据您的观察,似乎在现代版本的Windows中使用稍微更高效的算法。 (似乎链接文档说明它描述的算法永远不会导致超过8个浪费的扇区。我没有尝试过数学,但也许它与你的卷这个事实有关“重新分析是使用4KB群集而不是文档为14GB磁盘指示的8KB群集 - 请参阅第20页的表格。”

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

如果要安装已格式化的磁盘,当然可以使用存储在磁盘上的值。