为什么当我读取文件时,处于奇怪一致位置的位会被翻转?

为什么当我读取文件时,处于奇怪一致位置的位会被翻转?

我正在尝试追踪发生在在 Win7x64 中,我不知道下一步该尝试什么。

这个问题最初是在将约 2TB 的数据迁移到新的家庭 NAS 时出现的;当我验证副本时,一小部分文件已损坏。这是去年 12 月的事了,从那时起,我就一直在断断续续地寻找这个问题。

每次“损坏”都是受影响文件中一个或多个位置上的单个位从 0 翻转为 1 或从 1 翻转为 0。当一次“运行”中多个文件受到影响时,翻转的方向每次都相同。

这似乎不是 RAM 问题;我的系统不支持 ECC RAM,但我进行了多次内存测试,没有发现任何错误。系统还可以连续运行数周,不会重新启动或发生任何意外崩溃(需要注意的是,我预计Firefox 会定期崩溃),但我有意避免任何涉及移动大量数据的操作,直到我能解决这个问题。没有 CD 翻录、视频转码等。

我所见过的每一个案例,翻转的位是十六字节数据块的第七个字节的低位。在大多数(如果不是全部)在我见过的案例中,带有翻转位字节块的字节位于偏移量...2x7 或...5X7。一个月左右后,我才开始真正认真地跟踪该级别的问题。

以下是来自具有 121 个位翻转的多 GB 视频文件的最初几个示例:

                                     vv
000A46B2D0  1:  d2 04 29 dc d9 bf 15 01 f9 34 50 b6 08 11 63 d4
            2:  d2 04 29 dc d9 bf 15 00 f9 34 50 b6 08 11 63 d4
000EC6B2D0  1:  32 51 26 4f ae a0 42 29 93 5d 64 43 a6 e2 ee ba
            2:  32 51 26 4f ae a0 42 28 93 5d 64 43 a6 e2 ee ba
000F46B2D0  1:  e8 67 bd 18 08 00 62 59 21 37 94 00 d0 34 67 cf
            2:  e8 67 bd 18 08 00 62 58 21 37 94 00 d0 34 67 cf
0018C6B2D0  1:  b3 6e 0b 97 4e 7d 77 ab f9 74 38 6a 30 ee 9c 44
            2:  b3 6e 0b 97 4e 7d 77 aa f9 74 38 6a 30 ee 9c 44
001F46B2D0  1:  7e 87 0a c3 17 50 7c 55 39 b9 95 20 b8 6d 75 1a
            2:  7e 87 0a c3 17 50 7c 54 39 b9 95 20 b8 6d 75 1a
                                     ^^

左侧的十位十六进制值是两个被比较的文件中字节的位置,十六对十六进制值是文件中从该位置开始的十六个字节。请注意每个十六进制值对列的第八个字节的值差异。相关性也发生在更高的级别;请注意,每个 16 字节行的第一个字节位于以 46B2D0 或 C6B2D0 结尾的偏移处。对于此特定文件中的所有 121 个错误都是如此。

虽然这个问题首先出现在大文件复制期间,但我不认为这本身是一个“复制”问题,而是在读取文件时发生了一些事情,因为我实际上不必将数据写回即可看到问题:

  • 在比较两组已知相同的文件时,第一次检查将返回错误,但当重新检查显示问题的特定文件时,它们的测试结果将相同。
  • 有一次,我进行了一次比较,其中位翻转发生在已知相同的对的 SOURCE 文件中,并且使用不同的工具(Beyond Compare、md5sum、我自己的字节级文件比较脚本,给出了上述输出)多次重新读取同一个文件,得到了相同的结果,但重新启动后,文件位比较再次显示为相同。根据这个结果,我假设所有重新读取都从缓存中提取了相同的坏数据。

它似乎也没有与特定的存储介质或我用来复制文件或随后进行比较的应用程序相关联:

  • 我见过文件复制时的行为对涉及消费者 NAS、USB3 连接的备份驱动器和两个不同的内部旋转盘片驱动器的所有可能组合和方向进行只读比较。(所有文件系统均为 NTFS。)
  • 我在验证使用 Windows 资源管理器、Robocopy、Beyond Compare 和 Teracopy(后者在验证阶段报告了校验和不匹配)中的拖放操作所制作的副本时,使用了包括 Beyond Compare(Hex View)在内的比较工具、我自己的字节级比较脚本,以及与先前生成的 md5sum 值的比较,都看到了这种行为。

我试图确定它是否与系统中存在任何特定进程有关,但考虑到每次比较过程需要多长时间以及错误发生的频率,这很困难。话虽如此,至少有一次我遇到了很多比较错误,我杀死了一个消耗大量内存的进程(CrashPlan 备份服务,这是一个疯狂的资源消耗者),之后比较过程的其余部分都没有错误。不过,无论该特定服务是否正在运行,我都可以重现该问题。

(由于我不太了解情况,所以从现在起,问题的回答变得有些难以捉摸。)

由于这看起来可能与 Windows 文件缓存有关,因此我使用 Sysinternals CacheSet 检查了消耗情况。我看到问题时的典型值是当前缓存大小约为 1Gb,峰值缓存大小为 1.5-1.7 GB。对于 8GB 系统来说,这似乎是合理的;我运行了很多占用大量 RAM 的进程,但系统从未感觉到内存特别受限。但是,工作集范围显示为 1MB - 1TB(!!),这绝对不合理。(我还使用 CacheSet 实验性地将最大工作集大小设置为 1Gb,但该设置在重启后无法继续使用——不确定这是否是预期的。)

在上述明显的错误读取位于缓存中的期间,我还使用 CacheSet 清除了缓存工作集,但随后读取“坏”文件时仍然显示问题,直到我重新启动。

发生错误读取时的工作集大小似乎并不重要。虽然我最近才开始检查,但 Sysinternals RamMap 显示,发生错误读取时,元文件活动/总值低至 200MB/250MB,这远远低于最大值。

可以这个问题,假设 Windows 显示损坏的 XMP 日期字段的当前日期。

我想这涵盖了迄今为止我所了解的有关这个问题的全部内容。

答案1

@Bob:看起来肯定是内存条坏了,尽管用 memtest86+ 测试了近 20 次才证明这一点。经验教训:1) 在深入研究软件/配置之前验证所有硬件,2) 永远不要相信内置的自检。感谢大家的帮助。

相关内容