Linux 下格式化 FAT32 分区,只是一个 mkfs.vfat 就行了吗?

转载网址: Linux 下格式化 FAT32 分区,只是一个 mkfs.vfat 就行了吗?

 

问题发现

首先不得不说的是,当年在我不了解如何格式化一个分区到 FAT32 类型时,我选择了百度,当时得到的答案是 mkfs.vfat device。虽然惊奇于为何如此简单,但却没做深究,后来学会了如何看 infopage、manpage,也没仔细研究这里面的问题。

直到现在,在种种偶然情况下,我恰好在研究制作启动盘中出现的问题,恰好在研究 windows bootsect.exe 原理,恰好用 qemu 模拟了不同的磁盘去在虚拟机里做实验,又恰好地注意到一个问题:我测试的是 FAT32,为什么有一部分盘,引导代码与其他的不一样?经过详细的分析,反推出了 bootsect.exe 的相关源码,这才知道,其中有一部分,是 FAT(准确说是 FAT16),而非 FAT32。
真实答案

经过查看了 man mkfs.vfat,我发现了其中有这么一个参数:

    -F FAT-SIZE
        Specifies the type of file allocation tables used (12, 16 or 32 bit). If nothing is
        specified, mkfs.fat will automatically select between 12, 16 and 32 bit, whatever fits
        better for the filesystem size.

-F 参数指定 FAT 的类型,可选的值有 12 位、16 位以及 32 位。当未指定时,mkfs.fat 会自动选择其中最合适的。

所以,mkfs.vfat device 不能保证你格式化得到的分区一定是 FAT32,它会自动决定。真正有效的方案,应该是使用 mkfs.vfat -F 32 device 才可。
(注:由于 FAT32 的设定限制,不支持小于 32MB 的分区,否则会导致簇数达不到要求,在某些情况可能导致系统识别出错。)
详细探究

或许让 mkfs.vfat 自己决定最佳的情况并不理想,但为什么有些情况下,就是 FAT32,而有些情况却不行?

经过研究发现,在 dosfstools 源码的 mkfs.fat.c 文件中,有两个函数起到了关键作用:establish_params 和 setup_tables。

函数 establish_params 对各种参数,比如每个扇区的字节数、一个簇有多少个扇区等,进行了初始设定,设定的来源包括用户指定参数、分区大小等。由代码中看出来,在用户未通过 -F 参数指定类型,且分区的大小达到了 512MB 时,程序自动采用 FAT32 类型。

而在 setup_tables 中的决定分区类型部分,则是根据之前函数中设置的簇大小,以及分区的信息,分别计算出使用 FAT12、FAT16、FAT32 时簇数目是多少。判断得到的簇数是否满足要求,如果是,则进行之后的检查及决定。如果不是,在一个确定的簇大小范围内(用户指定或者自动判断),它会尝试增加簇大小,直到满足要求。最后,根据何种情况下能取得更多的簇数,选择是使用 FAT12 或者 FAT16。

可见,mkfs.vfat 除了判断分区大小达到 512MB 时才使用 FAT32 类型,小于这个值,则只在 FAT12 或 FAT16 之间选择,就连源码中都有这么一个注释:

    FAT32 is (not yet) choosen automatically

就实际状况而言,我们的存储介质一般并不小,不大可能低于 512MB,或许不指定 -F 参数的答案并非错误,只是不严谨;而当我们进行一些研究时,或者恰好碰上小于 512MB 的存储介质时,问题才得以显现。
总结

不要懒得翻手册查资料。别人的答案并非是对的,除了实践以外,为了确保自己得到正确的知识,至少要翻阅手册,或者多加测试。有条件可以阅读他人的代码,这样不仅能学到知识,还能更加了解程序的工作流程。
 

你可能感兴趣的:(Linux)