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

标签 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 文档中指定:

Note that on a FAT32 volume the BPB_RootEntCnt value is always 0, so on a FAT32 volume RootDirSectors is always 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 大小。

编辑:

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 个扇区?

最佳答案

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

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

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

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

如果您正在挂载已格式化的磁盘,您当然会使用存储在磁盘上的值。

关于windows - Windows 7 格式化驱动器上的 FAT32 文件分配表大小超出 FAT32 规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38876527/

相关文章:

python - 如何检查另一个程序中的任务是否已完成?

windows - 如何更换!优雅地分批处理到 %21?

.net - 修改创建日期属性

linux - 递归目录时 Bash 内存 "leak"

logging - microSD 卡 FAT 模块

Android:在特定 SD 卡上禁用 fsck_msdos

c++ - 添加库后qt应用程序启动时崩溃

node.js - Nodemon 在 Windows Docker 环境中不重启

c - 如何从引导扇区识别 FAT16 或 FAT32

java - 在 Windows 上格式化 Fat32 USB 驱动器