USB 磁盘写入延迟(Windows)

Posted

技术标签:

【中文标题】USB 磁盘写入延迟(Windows)【英文标题】:usb disk write latency (windows) 【发布时间】:2012-03-27 21:06:00 【问题描述】:

我正在从优先级最低的线程写入 USB 磁盘,使用分块缓冲区写入,但有时系统总体上会滞后于此操作。如果我只禁用写入磁盘,一切正常。我不能使用 Windows 文件操作 API 调用,只能使用 C 编写。所以我想也许有一个 WinAPI 函数来打开/关闭 USB 磁盘写入缓存,我可以将它与 FlushBuffers 或类似的替代方案结合使用?操作的驱动器数量未定义。

理想情况下,我希望使用写调用和缓存永远不会滞后,如果透明地执行也是可以的。

编辑: 只写操作上的_O_SEQUENTIAL 标志在这里有用吗?

【问题讨论】:

我不明白。你想永远不要阻塞,但你正在使用超低线程优先级?这没有任何意义。你的外部问题到底是什么? @david-schwartz 写操作在某些频率下会导致整体系统滞后。我不关心线程中的阻塞,我的意思是系统滞后......,会纠正问题 您有更多关于问题所在的详细信息吗?例如,写入量是否会将其他信息推出缓存?如果你知道你在做什么,你可以non-temporal writes that bypass the disk cache。 似乎 Windows 在磁盘访问方面存在一些基本问题。仅从带有坏扇区的 USB 卷中读取数据会导致整个系统剧烈停止(Windows 7 64 位) 嗯,所描述的症状让我想起了这一点:***.com/questions/7856251/… ...我倾向于同意 Sergey,Windows 有问题 :( 【参考方案1】:

尝试降低线程的 I/O 优先级。 见这篇文章:http://msdn.microsoft.com/en-us/library/windows/desktop/ms686277(v=vs.85).aspx 特别是为您的 IO 线程使用 THREAD_MODE_BACKGROUND_BEGIN。 警告:这在 Windows XP 中不起作用

【讨论】:

因此,如果您已经将 IO 线程的优先级降低到最低,我想您不太关心 IO 速度(它只是必须发生)。所以我建议然后使用类似于 Windows Defragmenter 的方法 - 检查当前磁盘 IO 级别,除非它们至少不做任何事情 - 我相信当 USB IO 阻塞主 HDD IO 时你会感到滞后 嗯,这可以工作。你有这方面的更多信息吗?我一定会去看看的 都是关于性能计数器 (msdn.microsoft.com/en-us/library/windows/desktop/…),但我从未真正从 WinAPI 访问过它们 小心,THREAD_MODE_BACKGROUND_BEGIN for IO 在 Windows Vista 上已损坏。 Mahmound,你能说得更具体点吗?还没听说过这个【参考方案2】:

线程优先级不会影响写入媒体过程中发生的延迟,因为它是由不关注调用线程优先级的文件系统/磁盘驱动程序在内核模式下完成的。

您可以尝试使用“T”标志 (_O_SHORTLIVED) 并在操作结束时刷新缓冲区,同时尝试减小缓冲区大小。

【讨论】:

【参考方案3】:

USB 有不同类型的数据传输,对于数据有 3 种: 1.批量转移, 2.同步传输,和 3.中断传输。

    批量传输提供:

    Used to transfer large bursty data.
    Error detection via CRC, with guarantee of delivery.
    No guarantee of bandwidth or minimum latency.
    Stream Pipe - Unidirectional
    Full & high speed modes only.
    

    批量传输适用于不需要在保证时间内交付的数据 USB 主机控制器对批量传输的优先级低于其他类型的传输。

    同步传输提供:

    Guaranteed access to USB bandwidth.
    Bounded latency.
    Stream Pipe - Unidirectional
    Error detection via CRC, but no retry or guarantee of delivery.
    Full & high speed modes only.
    No data toggling.
    

    同步传输连续且周期性地发生。它们通常包含时间敏感信息,例如音频或视频流。如果音频流中的数据存在延迟或重试,那么您会预料到一些包含故障的不稳定音频。节拍可能不再同步。但是,如果一个数据包或帧不时被丢弃,则侦听器不太可能注意到它。

    中断传输提供:

    Guaranteed Latency
    Stream Pipe - Unidirectional
    Error detection and next period retry.
    

    中断传输通常是非周期性的、小型设备“启动”的通信,需要有限的延迟。中断请求由设备排队,直到主机轮询 USB 设备请求数据。

从上面看,你似乎想要一个保证延迟,所以你应该使用 Isochronous 模式。您可以使用一些库,例如 libusb,或者您可以在 msdn 中阅读更多内容

【讨论】:

USB 设备(磁盘)决定了它处理的传输模式。如果它不做中断模式,那么它就不会。我认为除了 BULK 传输之外,没有任何 USB 驱动器可以执行任何操作。 好吧,我强烈建议您在投反对票之前阅读更多内容,并且“我不认为...”不是放弃可能实际上对某人有帮助的潜在答案的可接受理由。回到主题,如果您想知道如何在 msdn 中阅读此article,可以中断和同步传输数据。你可以阅读更多here。和技术细节在这个article。 OP 要求他的 IO 不阻塞其他 IO,不要相信他想要保证延迟,实际上恰恰相反。 @Showang You:当然可以通过中断和等时传输来传输数据。那不是我的意思。只是 USB 大容量存储类指定了批量传输(显然,除非您正在处理软盘)。由于问题提到了“USB 磁盘”,我认为假设它涉及 USB MSC 是公平的,因此只有 BULK 传输是相关的。希望这能澄清问题。仅供参考:我已经为设备实现了 USB MSC,因此我对 USB 传输的工作原理有一个相当了解。【参考方案4】:

要找出导致系统挂起的原因,您首先需要深入了解 Windows 挂起。当您遇到挂起时,Windows 在做什么?

要找出这一点,您可以进行内核转储。如何获取和分析内核转储读取here。

根据您获得的结果,您需要决定是否有任何事情在您的控制范围内您可以做些什么。由于您使用第三方库来编写,除了设置IO priority,线程或进程级别的线程优先级外,您几乎无能为力。如果为您提供了针对特定 CRT 的链接库,您可以尝试构建自己的自定义版本,例如每次写入后刷新,以防止操作系统进行写入组合以仅将大块数据写入磁盘。

编辑1

最好的办法是在每次写入后刷新设备。这可能会强制操作系统刷新任何待处理的数据并将当前待处理的写入写入磁盘,而不会将写入缓存到一定数量。

第二个最好的办法是简单地在每次写入后等待,让操作系统有机会在一定时间间隔后将待处理的更改写入磁盘。

如果您更深入地了解性能,您应该尝试XPerf,它有一个不错的 GUI,甚至可以显示您的进程确实挂起的调用堆栈。 Windows 团队和 MS 的许多其他团队使用此工具对挂起experiences 进行故障排除。 Windows 8 SDK 附带了具有更多功能的最新版本。但请注意,Xperf 仅适用于 OS > Vista。

【讨论】:

以上是关于USB 磁盘写入延迟(Windows)的主要内容,如果未能解决你的问题,请参考以下文章

Linux 上使用 gnome-disks 格式化 usb 磁盘,成NTFS格式,可以给Windows直接使用了。

使用Windows 10自带命令创建可引动USB启动盘

Linux 上使用 gnome-disks 格式化 usb 磁盘,成NTFS格式,可以给Windows直接使用了。

从 Windows CLI 刷新磁盘写入缓存

有成功吧 windows 10 做成VHD在移动硬盘里启动的吗

有没有办法在 Windows 中使用 C# 以编程方式禁用磁盘驱动器上的写入缓存策略?