jjzjj

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

coder 2024-06-05 原文

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

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

  1. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  2. Ruby 日期参数超出范围 - 2

    我正在尝试使用在我的代码中是动态的Time.local来安排时间。在每个月的第一天,我传递的值是Time.local(2009,9,-1,0)。在PHP中,这会将时间设置为上个月的最后一天。在ruby​​中,我只是得到“ArgumentError:参数超出范围”。是我用错了方法还是什么?谢谢。 最佳答案 您应该使用DateTime类而不是Time。(您可能需要先require'date'并安装activesupportgem。)它比Time更通用,并且可以用DateTime.civil(2009,9-1,-1,0)做你想做的事。为天

  3. ruby - gem 规范失败 - 2

    我正在为毕业设计开发GEM,TravisCI构建不断失败。这是我在Travis上的链接:https://travis-ci.org/ricardobond/perpetuus/builds/8709218构建错误是:$bundleexecrakerakeaborted!Don'tknowhowtobuildtask'default'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_wrapper:14:in`eval'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_

  4. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  5. ruby - 如何禁止在 RSpec 中显示挂起(跳过)的规范? - 2

    我有几个跳过的规范。Pending:(Failureslistedhereareexpectedanddonotaffectyoursuite'sstatus)1)...#Notyetimplemented#./spec/requests/request_spec.rb:22如何抑制未决规范的输出? 最佳答案 您可以添加以下配置选项以从运行中过滤掉所有待处理的规范:RSpec.configuredo|config|config.filter_run_excludingskip:trueend此外,here是一个更详细的抑制输出的建议

  6. ruby-on-rails - 从帮助器规范中 stub 一个帮助器方法 - 2

    我正在构建Rails应用程序并使用RSpec制定测试。我为我正在创建的名为current_link_to的方法编写了测试。此方法应该检查当前页面是否对应于我传递给它的路径,并将current类添加到生成的链接中,以防它匹配。这是规范:require"spec_helper"describeApplicationHelperdodescribe"#current_link_to"dolet(:name){"Products"}let(:path){products_path}let(:rendered){current_link_to(name,path)}context"whenthe

  7. ruby-on-rails - 在 RSpec 中编写请求规范的正确方法是什么? - 2

    tl;dr:跳到最后一段最近一直在尝试使用RSpec的requestspecs做一些更有针对性的测试。我的测试主要是这样的:通用cucumber功能规范,即用户转到带有评论的帖子,对评论点赞,作者获得积分modelspecs当模型实际上具有某些功能时,即User#upvote(comment)controllerspecs我在其中stub了大部分内容,只是试图确保代码按照我期望的方式运行viewspecs当View中有一些复杂的东西时,例如仅在用户尚未投票时呈现upvote链接,这些被stub为好吧问题是当我有一些导致错误的特定场景时,一切似乎都在我无法重现它的模型/View层中工作。

  8. ruby-on-rails - 加速 RSpec 请求规范的方法 - 2

    我有33个规范以大约5秒的速度运行,以这种速度运行会导致测试套件变慢。我追踪到请求规范(4秒以上),因为模型规范只用了一小部分时间。我已经检查过,我的请求规范没有任何过于复杂或不必要的东西,所以我不知道该去哪里让它们更快,而不是只在推送代码之前运行它们以确保一切正常.加快请求规范的最佳方法是什么? 最佳答案 我使用Spork来加速我的测试。它保持整个环境加载以赢得时间。看看这个博客:http://ykyuen.wordpress.com/2010/12/14/rails-running-rspec-with-spork-test-s

  9. ruby-on-rails - Rspec 的 instance_double 创建间歇性规范失败 - 2

    我在使用instance_double时遇到间歇性测试失败。我有一个包含4个规范的文件。这是来源:require'rails_helper'describeSubmitPostdobefore(:each)do@post=instance_double('Post')allow(@post).toreceive(:submitted_at=)endcontext'onsuccess'dobefore(:each)doallow(@post).toreceive(:save).and_return(true)@result=SubmitPost.call(post:@post)endit

  10. ruby - 规范测试基于 EventMachine 的(Reactor)代码 - 2

    我正在尝试整个BDD方法并想测试AMQP基于Vanilla的方面Ruby我正在写的应用程序。选择Minitest后作为与其他名副其实的蔬菜框架不同的平衡功能和表现力的测试框架,我着手编写此规范:#File./test/specs/services/my_service_spec.rb#Requirementsfortestrunningandconfigurationrequire"minitest/autorun"require"./test/specs/spec_helper"#Externalrequires#MinitestSpecsforEventMachinerequire

随机推荐