即使驱动程序没有完成irp,同步I/O是否可以自动取消?
在用户模式代码中:
CreateFile(A device);
ReadFile(The device handle); // synchronously
在相应驱动程序的 IRP_MJ_READ 调度例程中:
// To hold the irp. It will never complete the irp.
// This driver doesn't even have a cancel routine.
Sleep(INFINITE);
当我在执行 ReadFile() 之后强制终止用户模式应用程序时,可以取消 I/O 吗?
如果是异步 I/O,则应用程序无法终止。
但是如果 I/O 是同步的,I/O 管理器会自动取消它吗?
如果是这样,怎么办?
In user mode code:
CreateFile(A device);
ReadFile(The device handle); // synchronously
In correspond driver's IRP_MJ_READ dispatch routine:
// To hold the irp. It will never complete the irp.
// This driver doesn't even have a cancel routine.
Sleep(INFINITE);
When I terminate the user mode app forcedly after do ReadFile(), can the I/O be canceled?
If it was asynchronous I/O, the app couldn't be terminated.
But if I/O is synchronous, does I/O manager cancel it automatically?
If so, how?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,异步和同步 I/O 都是通过 IRP 实现的。用户模式 API ReadFile 调用内部 NT API(系统调用)NtReadFile,最终发送 IRP。如果驱动程序返回 STATUS_PENDING,NT API 将返回相同的状态。如果用户模式应用程序对 ReadFile 进行同步调用,ReadFile 将等待文件句柄以等待 I/O 完成。驱动程序还可以同步完成 IRP(无论用户模式 API 的调用方式如何)。我认为这就是您感兴趣的情况。IRP
与发送它们的线程相关联。因此,当线程终止时(例如由于终止进程),I/O 管理器会尝试取消与该线程关联的所有 IRP。在所有 IRP 完成之前,线程无法终止。
当关闭句柄时,I/O 管理器会向驱动程序发送 IRP_MJ_CLEANUP 和 IRP_MJ_CLOSE。在这种情况下,是驱动程序取消挂起的IRP(或者只是以取消的方式完成它们)。
取消 IRP 的能力取决于驱动程序的配合。驱动程序必须通过调用 IoSetCancelRoutine。
如果驱动程序只是阻塞而不使 IRP 可取消,则 IRP 将不会被取消。
First, both both asynchronous and synchronous I/O are implemented with IRPs. The user-mode API ReadFile calls an internal NT API (system call) NtReadFile which ends up sending an IRP. If the driver returns STATUS_PENDING, the NT API will return same status. If the user-mode application makes a synchronous call to ReadFile, ReadFile will wait on the file handle for the I/O to complete. The driver can also complete the IRP synchronously (regardless of the way the user-mode API is called). I think that this is the case you are interested in.
IRPs are associated with the thread that sent them. So when a thread is terminated (for example due to killing the process), the I/O manager attempts to cancel all the IRPs that are associated with that thread. The thread cannot terminate until all the IRPs are completed.
When you close a handle, the I/O manager sends the driver IRP_MJ_CLEANUP, and IRP_MJ_CLOSE. It is the driver that cancels pending IRPs (or just completes them as canceled) in this case.
The ability to cancel an IRP depends on the cooperation of the driver. The driver must explicitly make the IRP cancelable by calling IoSetCancelRoutine.
If the driver just blocks without making the IRP cancelable, the IRP will not get canceled.
在 Vista 及更高版本上,您可以使用 CancelSynchronousIo 将线程的所有挂起 IO 标记为已取消。 NtCancelIoFile可用于取消IO对于特定文件。 (免责声明:我还没有实际测试过这个函数)
这些调用的效果会有所不同,具体取决于驱动程序实现。
从用户模式应用程序来看,效果应该是立即取消,即使驱动程序可能会等待很长时间才能完全清除 IO 请求。
MSDN:I/O 完成/取消指南
On Vista and up, you can use CancelSynchronousIo to mark all pending IO for a thread as canceled. NtCancelIoFile can be used to cancel IO for a specific file. (disclaimer: I haven't actually tested this function)
The effects of these calls will vary, depending a.o. on the driver implementation.
Seen from the user mode application, the effect should be an immediate cancellation, even though the driver may keep waiting for a long time before the IO request is completely cleaned up.
MSDN: I/O Completion/Cancellation Guidelines ???? has a lot of information on cancellation: