65.9K
CodeProject 正在变化。 阅读更多。
Home

在老旧硬件上处理大文件的容错性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (8投票s)

2012 年 9 月 14 日

CPOL

8分钟阅读

viewsIcon

26581

downloadIcon

1043

WPF 和窗体工具,用于在“脾气暴躁”的硬件上更好地复制和比较大文件。呼吁软件制造商考虑容错处理。

Sample Image

引言

如果您在移动、复制或使用外部连接磁盘上的大文件时没有遇到任何问题,那么本文可能不会引起您的兴趣。如果您怀疑您的外部硬件在使用大文件时有时会发生微小故障,那么这些容错实用工具应该可以帮助您复制或比较到/从/在外部磁盘上的文件。

背景

我使用 Norton Ghost (http://www.symantec-norton.com/) 将我的硬盘备份为单个文件映像。Norton Ghost 是一个优秀的产品,我强烈推荐它。但是,我偶尔需要移动备份或“恢复点”,或者实际恢复磁盘卷。这时,我就会遇到以下类型的问题。下面的截图显示了 Symantec Recovery Point Browser 的 Verify Recovery Point... 对话框。

recovery point check dialog

WILLM_C_Drive002.v2i 位于 USB 连接的驱动器 T: 上。此截图显示了验证失败。

failed integrity verification

这张截图显示了在上面一次失败的运行后立即对同一文件进行的成功验证。

successful integrity check

当使用 Beyond Compare (http://ScooterSoftware.com) 比较大型虚拟机映像或视频文件时,也可能发生这种情况。Beyond Compare 是一个优秀的产品,我强烈推荐它。由于 Beyond Compare 提供了显示比较文件之间差异的功能,因此它必须在报告比较失败之前扫描两个文件的全部内容。这些是部分截图,显示了基于 CRC 的 Beyond Compare 文件比较出错。

Beyond Compare screenshot LHS

Beyond Compare screenshot RHS

这张截图显示了使用本文中的第二个实用工具 **Sequence Comparer** 比较这些文件的结果。

Sequence Comparer successful compare

我想要的是一种复制大文件的方法,并在复制完成后知道它是一个可靠的副本。我也想要一种方法来证明文件是副本,如果复制是由文件资源管理器通过简单的复制粘贴完成的。

一些见解

数字机器之所以被认为是可靠的,很大程度上是因为它们是数字的——数字位中没有模拟的变数。那么,为什么在重复进行这些应用程序的验证或比较时会出现不同的结果呢?

这时我提出了我的技术术语“脾气暴躁的硬件”,意思是接近数字理想状态,但在长时间使用中偶尔会出错的硬件。这是一张我用来解释导致大文件复制或比较出错的“脾气暴躁”硬件的图。

RAM to Hard Disk diagram

系统 RAM 是“脾气暴躁”硬件的一部分,因为内存会受到电压瞬变或高温的影响。

磁盘缓存是系统 RAM 的一部分。磁盘缓存中显示的小矩形代表最近读取或正在收集以更有效地分块写入的数据块。这些小矩形的用途和替换可能会出现罕见的竞争条件,这些竞争条件只在大文件处理外部磁盘时才会显现。

大多数磁盘控制器都有自己的扇区数据缓存,这可能会受到与系统 RAM 磁盘缓存相同的罕见问题的困扰。

物理硬盘是“脾气暴躁”硬件的一部分,因为,有什么能比检测旋转的铁锈颗粒的磁性状态更“脾气暴躁”呢?是的,有 CRC 和 ECC 机制来检测和纠正坏比特,但是什么让这些机制不“脾气暴躁”呢?

然后是 USB 控制器。这是一张 USB 控制器的图。

USB Controller diagram

大致来说,如果信号的“弹性”不够好,可能会选择一个错误的颜色位。或者诸如此类。我可能没有完全弄清楚细节,但我怀疑外部磁盘控制器(USB、eSATA 等)是无法持续处理大文件的硬件中最“脾气暴躁”的部分。我不记得在只涉及内部 IDE 或 SATA 磁盘时有过任何“脾气暴躁”的行为。那么,该怎么办?

使用代码

最基本的容错方法是**重试**那些未能达到预期结果的操作。对于文件复制,这意味着读取写入的数据,将其与原始数据进行比较,如果发现差异,则重试写入、读取和比较操作。我发现的特殊神奇秘诀是,每次重试段时,都比前一次尝试稍微减小文件偏移量。我相信这有助于防止磁盘缓存短路写入-然后-读取序列,从而获取真实的硬盘位。

文章开头所示的 **Verify Copy** 是一个 WPF 应用程序,它通过重试来进行文件复制。它使用 System.Windows.Controls.Primitives 元素和 System.Windows.Input.MediaCommands 像媒体播放器一样“开始”、“暂停”和“停止”文件复制操作。当 Verify Copy 被最小化时,进度会在任务栏图标中显示,将鼠标悬停在图标上可以显示开始、停止、复制控件。当然,您不必最小化此实用工具来使用它。这只是这种 WPF 应用程序的一个便捷功能。

这是 Verify Copy 在任务栏的截图。

Verify Copy from the Task Bar

此处未显示光标,但它曾悬停在迷你显示中的“暂停”按钮上。

Verify Copy 使用三遍策略。第一遍执行基本的读取原始、写入副本、读取副本和比较序列,最多进行 2 次重试。如果在此过程中用尽了重试次数,Verify Copy 将会使文件复制失败。

第二遍是读取原始、读取副本和比较阶段,该阶段在复制文件完全写入后进行验证,最多进行 2 次重试。在此阶段,磁盘缓存短路应该相对不存在。如果用尽了重试次数,将记录该段在文件中的位置。

最后,第三遍尝试重新写入复制文件中在第二遍重试失败的任何段。请注意,在本文开头 Verify Copy 的截图中,右下角显示了“所需修复 2”“已修复 1”。这张截图是在第三遍进行到一半时拍摄的。另请注意,在进度条正下方显示的深金黄色矩形。Verify Copy 每次重试时都会更改此矩形的颜色。

如果您发现 Verify Copy 占用了过多的 CPU 资源,影响您进行其他工作,请尝试“暂停”以暂停文件复制。根据使用的缓冲区大小,Verify Copy 可能需要一些时间才能响应。单击“恢复”(在“暂停”生效后显示)将恢复文件复制。

如果您从源代码和解决方案构建 Verify Copy,有两个条件编译符号可以使用。如果定义了 DEFEAT_CACHE,Verify Copy 将使用仅受可用内存限制的大读取/写入缓冲区。在写入副本之前,将使用一个额外的步骤来预先写入目标文件。这应该可以完全消除大多数系统上的磁盘缓存短路,但会增加验证复制所需的时间。MEMORY 可以与 DEFEAT_CACHE 一起定义,这将对读取的原始缓冲区在使用之前和之后进行 CRC-32 检查,以验证其在使用过程中是否已更改。这也需要额外的时间,我可以报告说使用此开关从未显示过我的读取原始内存缓冲区(RAM)是“脾气暴躁”的。

最后,如果您想在 Visual Studio 调试器中构建和运行 Sequence Comparer,您需要在 Solution Explorer 中更改启动项目。这是选择该菜单的图片。

Set Startup Menu

理念与呼吁

作为软件制造商,您如何处理“脾气暴躁”的硬件?我认为可以采取两种理念。

  1. 假设并要求用户拥有完美的硬件。只有少数用户确实拥有问题硬件,并且试图为不完美的硬件进行任何容错处理可能会影响产品的可信度。如果考虑到了“脾气暴躁”的硬件,也许软件也会被视为可能“脾气暴躁”。
  2. 尽量给用户完成他们使用产品所需任务的每一个机会。为了避免牵连,将容错作为一项意图明确的选项提供给有迫切需求的用户的。

我的呼吁是,软件制造商应该考虑第二种理念。

新增内容

我在 Windows 7 x86 和 Windows 8 x64 上测试了演示代码。已修复 Verify Copy 中报告的“所需修复”的 bug,并在复制完成后将源文件的创建和最后写入日期时间设置到目标文件中。Sequence Comparer 现在会记住文件 1 和文件 2 的最后一个文件夹,以便在比较两个文件夹之间的多个文件时提供帮助。我发现 SequenceCompare 比 CRC32 classic、slice-by-4 或 slice-by-8 检查更快,因此没有添加选择“二进制”或“Crc”比较的选项。

我强烈推荐 LaCie eSATA PCI 卡(SISMO 设计),适用于配备“脾气暴躁”硬件的 PCI 系统。我发现它的信号“弹性”非常好,自使用此硬件代替我之前使用的 USB 适配器以来,只遇到了一两次比较重试。我还注意到,eSATA 连接磁盘的读写访问速度现在比我的内部 EIDE 磁盘还要快。USB 连接磁盘的性能大约是我内部磁盘的 1/5(确实很“脾气暴躁”)。

参考文献

  1. http://elegantcode.com/2011/03/01/wpfwindows-7-task-bar-part-threeoverlay-icons/ - 关于 Win 7 任务栏功能的优秀系列文章的第三部分。
  2. http://www.codeproject.com/Articles/96498/WPF-Integrating-our-application-with-the-Windows-7 - 2010 年关于在 .NET 3.5 和 4.0 中使用图标叠加和进度条的文章。
  3. http://msdn.microsoft.com/en-us/library/ms752293.aspx - 我需要这个来得到 PauseImage 叠加的几何图形。
  4. http://msdn.microsoft.com/en-us/library/system.windows.window.icon%28v=vs.100%29.aspx - 在 XAML 中指定任务栏图标。
  5. http://www.codeproject.com/Articles/2380/Cyclic-Redundancy-Check-CRC32-HashAlgorithm - 我添加了 public UInt32 ComputeHash(byte[] byteArray, bool AsUInt32)
  6. http://stackoverflow.com/questions/778678/how-to-change-the-color-of-progressbar-in-c-sharp-net-3-5 - 未来工作。
  7. http://technet.microsoft.com/en-us/library/bb742613.aspx - 文件缓存性能与调优。比我现在能深入研究的更深。
  8. http://www.blackwasp.co.uk/ExtensionMethods.aspx - 关于扩展方法的一个介绍。
  9. http://geekswithblogs.net/NewThingsILearned/archive/2008/08/25/refresh--update-wpf-controls.aspx - 解释 Refresh 扩展工作原理的博客。
  10. http://www.pinvoke.net/default.aspx/kernel32.getdiskfreespace - GetDiskStuff.cs 中使用的 GetDiskFreeSpace

历史

提交至 CodeProject 2012 年 9 月 4 日。
首次更新 2012 年 9 月 13 日。请参阅“新增内容”。

© . All rights reserved.