我正在编写一个嵌入式 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/