将文件写入 USB 记忆棒会导致意外删除时文件损坏/锁定
我正在编写一个后台应用程序,以使用“优化快速删除”策略集将文件循环复制到 USB 记忆棒。 但是,如果在此过程中部分移除该棒(特别是在下面的 WriteFile() 调用中,该调用将返回错误文件未找到),则应用程序将挂起,任何其他应用程序将永久无法访问该驱动器,并且无法关闭 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 下默默修复?
谢谢你的帮助。
I'm writing a background application to copy files in a loop to a USB stick with the "Optimize for quick removal" policy set. However, if the stick is removed part way through this process (specifically in the WriteFile() call below, which returns ERROR FILE NOT FOUND) the application hangs, the drive is then permanently inaccessible from any other application and the PC cannot be shutdown/logged off/restarted etc. All running instances of Windows Explorer also hang as a result.
I have traced the issue to the CloseHandle() call made after the stick is removed and the above error occurs. Its almost as if CloseHandle() is blocking indefinitely in the driver somewhere because the stick is no longer there? Anyway, I have managed to get past this issue by simply skipping the CloseHandle() call if WriteFile() returns ERROR FILE NOT FOUND. However, this leads to another problem where, every so often, a file gets irrecoverably corrupted and the only way to fix it is using chkdsk, or reformat the stick.
Note that this only happens on XP (SP2 and 3), Vista does not seem to suffer from the issue. A snippet of the code follows:
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);
}
}
I've tried pretty much every combination of flags for CreateFile() all to no avail. Has anybody seen this before or have any good ideas how to avoid either of the two problems occuring. Is what I'm seeing a driver problem which has been silently fixed under vista?
Thanks for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
听起来很有道理。 CloseHandle() 最终将发出一个文件系统 IRP,并且您没有使用非阻塞 I/O,因此 IRP 将是同步的,但看起来实际的文件系统突然从文件系统驱动程序下面消失了,即IRP 永远不会完成。 这意味着您已经被塞满了 - 导致发出文件系统 IRP 的用户模式函数调用将永远不会返回。
尝试使用非阻塞 I/O - 这将很可能帮助您解决这个问题,至少从不挂起的角度来看。 您仍然会遇到资源丢失等问题,因为 IRP 仍然会被传递,并且几乎肯定不会回来,但至少您不会阻塞它。
顺便说一句,“优化快速删除”是为了减少正在进行的缓存量,并可能影响文件系统的写入顺序以减少损坏的机会; 我非常怀疑它的目的是在写入期间文件系统离开时保留文件系统!
您不应该对这会杀死文件系统感到惊讶。
Sounds reasonable. CloseHandle() will ultimately emit a file system IRP and you're not using non-blocking I/O, so that IRP will be synchronous, but it looks like where the actual file system has abruptly disappeared from underneath the file system driver, that IRP is never completed. Which means you're stuffed - the user-mode function call which lead to the file system IRP being issued will never return.
Try using non-blocking I/O - that will prolly get you around this problem, at least from the point of view of not hanging. You will still be experiencing resource loss and the like, since the IRP will still be passed down and almost certainly still won't be coming back up, but at least you won't be blocking on it.
BTW, "optimize for quick removal" is I would say designed to reduce the amount of caching that goes on and perhaps influence the order of writes to the file system to reduce the chance of corruption; I extremely doubt it is intended to preserve the file system in the event of file system departure during a write!
You should not be surprised that this kills the file system.
这似乎是驱动程序的问题。
您必须释放驱动程序的所有句柄,以使其自行清理,并释放窗口以卸载它。 如果您不这样做,驱动程序会认为它仍然对设备负责,即使它发生了变化。
在用户模式下您无法避免此问题。
放弃句柄只会将问题转移到稍后阶段(例如退出程序,以便Windows尝试关闭所有放弃的打开句柄。)
This seems to be a driver problem.
You must free all handles to a driver, to let it cleanup itself, and windows to unload it. When you don't do that, the driver thinks it is still responsible for the device, even though it changed.
You cannot escape this problem in User-Mode.
Abandoning the handle just transfers the problem to a later stage (e.g. Quitting your program, so that windows tries to close all your abandoned open handles.)
关于挂起问题:您可以生成一个单独的线程进行写入,从主线程监督写入过程,并在写入线程花费的时间可疑时中止写入线程。 换句话说:实现异步写入并寻找超时。
About the hanging problem: You could spawn a separate thread for writing, supervise the writing process from the main thread and abort the writing thread if it takes suspiciously long. In other words: Implement the writing asynchronously and look for a timeout.
难道是文件系统驱动程序的问题而不是硬件驱动程序的问题? 您可能会发现,如果使用 NTFS,问题就会消失。
Could it be a problem with the filesystem driver rather than the hardware driver? You might find that if you use NTFS the problem goes away.