【发布时间】: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 扇区的数字不同?
【问题讨论】: