1

我正在编写一个后台应用程序,以将文件循环复制到带有“优化以快速删除”策略集的 USB 记忆棒。但是,如果在此过程中(特别是在下面的 WriteFile() 调用中,它返回 ERROR FILE NOT FOUND)中删除了存储棒,则应用程序挂起,则驱动器将永久无法从任何其他应用程序访问,并且 PC 无法关闭/注销/重新启动等。所有正在运行的 Windows 资源管理器实例也会因此挂起。

我已将问题追溯到移除棒后进行的 CloseHandle() 调用并发生上述错误。几乎就好像 CloseHandle() 无限期地阻塞在某个地方的驱动程序中,因为棒不再存在?无论如何,如果 WriteFile() 返回 ERROR FILE NOT FOUND,我通过简单地跳过 CloseHandle() 调用来解决这个问题。但是,这会导致另一个问题,即文件每隔一段时间就会被不可恢复地损坏,修复它的唯一方法是使用 chkdsk 或重新格式化存储棒。

请注意,这只发生在 XP(SP2 和 3)上,Vista 似乎没有遇到此问题。代码片段如下:

HANDLE hFile = CreateFile(szFile, 
                          GENERIC_WRITE, 
                          FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
                          NULL,
                          CREATE_ALWAYS,
                          FILE_FLAG_WRITE_THROUGH,
                          NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
    if (!WriteFile(hFile, pBuffer, dwBufferSize, &dwWritten))
    {
        int nLastError = GetLastError();
    }

    // If usb stick is removed during WriteFile(), ERROR_FILE_NOT_FOUND usually      results.
    // If handle is closed at this point then drive is inaccessible.
    // If CloseHandle() is skipped, then file corruption occurs instead
    if (nLastError != ERROR_FILE_NOT_FOUND)
    {
        CloseHandle(hFile);
    }
}

我已经尝试了 CreateFile() 的几乎所有标志组合都无济于事。有没有人以前见过这个或有任何好主意如何避免发生这两个问题中的任何一个。我看到的驱动程序问题是否已在 vista 下静默修复?

谢谢你的帮助。

4

4 回答 4

2

几乎就好像 CloseHandle() 无限期地阻塞在某个地方的驱动程序中,因为棒不再存在?

听起来很合理。CloseHandle() 最终将发出一个文件系统 IRP,并且您没有使用非阻塞 I/O,因此 IRP 将是同步的,但看起来实际文件系统突然从文件系统驱动程序下方消失了,即IRP 永远不会完成。这意味着你被塞满了——导致发出文件系统 IRP 的用户模式函数调用将永远不会返回。

尝试使用非阻塞 I/O - 至少从不挂起的角度来看,这将帮助您解决这个问题。您仍然会遇到资源丢失等问题,因为 IRP 仍将被传递,并且几乎可以肯定仍然不会恢复,但至少您不会阻止它。

顺便说一句,我会说“为快速删除而优化”旨在减少正在进行的缓存数量,并可能影响写入文件系统的顺序以减少损坏的机会;我非常怀疑它是否打算在写入期间文件系统离开的情况下保留文件系统!

你不应该对这会杀死文件系统感到惊讶。

于 2009-03-25T17:48:03.580 回答
1

这似乎是驱动程序的问题。

您必须释放驱动程序的所有句柄,让它自行清理,并释放 Windows 来卸载它。如果你不这样做,驱动程序认为它仍然对设备负责,即使它发生了变化。

您无法在用户模式下逃避这个问题。

放弃句柄只是将问题转移到稍后阶段(例如退出程序,以便 Windows 尝试关闭所有放弃的打开句柄。)

于 2009-03-25T14:07:11.740 回答
0

关于挂起问题:您可以生成一个单独的写入线程,从主线程监督写入过程,如果需要很长时间,则中止写入线程。换句话说:异步实现写入并寻找超时。

于 2009-03-25T11:48:39.123 回答
0

可能是文件系统驱动程序而不是硬件驱动程序有问题吗?您可能会发现,如果您使用 NTFS,问题就会消失。

于 2009-03-26T10:02:48.807 回答