取消 UMDF 中的 I/O 请求

警告

UMDF 2 是最新版本的 UMDF,取代了 UMDF 1。 所有新的 UMDF 驱动程序都应使用 UMDF 2 编写。 未向 UMDF 1 添加新功能,并且较新版本的 Windows 10 上对 UMDF 1 的支持有限。 通用 Windows 驱动程序必须使用 UMDF 2。

存档的 UMDF 1 示例可在 Windows 11 版本 22H2 - 2022 年 5 月驱动程序示例更新中找到。

有关详细信息,请参阅使用 UMDF 入门

应用程序、系统或驱动程序可以取消设备正在进行的 I/O 操作 (例如从磁盘) 读取多个块的请求。 如果取消设备的 I/O 操作,I/O 管理器将尝试取消与 I/O 操作关联的所有未处理的 I/O 请求。 设备的驱动程序可以注册,以便在 I/O 管理器尝试取消 I/O 请求时收到通知,并且驱动程序可以通过以完成状态为HRESULT_FROM_WIN32 (ERROR_OPERATION_ABORTED) 来完成 它们来取消其拥有的请求。

框架处理基于框架的驱动程序的某些取消工作。 如果取消了设备的 I/O 操作,则框架完成(完成状态为 HRESULT_FROM_WIN32 (ERROR_OPERATION_ABORTED) )与取消的操作关联的以下 I/O 请求:

由于框架取消这些请求,因此不会将这些请求传递给驱动程序。

框架向驱动程序传递 I/O 请求后,驱动程序拥有该请求,并且框架无法取消该请求。 此时,只有驱动程序可以取消 I/O 请求,但框架必须通知驱动程序应取消请求。 驱动程序通过提供 IRequestCallbackCancel::OnCancel 回调函数来接收此通知。

有时驱动程序从 I/O 队列接收 I/O 请求,但驱动程序会将请求重新排到同一个或其他 I/O 队列,以便以后处理,而不是处理该请求。 例如,框架可能会向驱动程序的请求处理程序之一传递 I/O 请求,驱动程序随后可能会调用 IWDFIoRequest::ForwardToIoQueue 将请求置于不同的队列中,或 调用 IWDFIoRequest2::Requeue 将请求放回同一队列。

在这些情况下,框架可以取消 I/O 请求,因为请求位于 I/O 队列中。 但是,如果驱动程序已为请求所在的 I/O 队列注册回调函数,则框架会在取消关联的 I/O 操作时调用回调函数,而不是取消请求。 如果框架调用驱动程序的回调函数,则驱动程序必须取消请求。

总之,取消 I/O 操作时,框架始终取消从未传递到驱动程序的所有关联 I/O 请求。 如果驱动程序收到请求,然后重新排队,框架将取消请求 (如果请求位于队列) ,除非驱动程序为 I/O 队列提供回调函数。

调用 MarkCancelable

驱动程序可以调用 IWDFIoRequest::MarkCancelable 来注册 IRequestCallbackCancel::OnCancel 回调函数。 如果驱动程序已调用 MarkCancelable,并且取消了与请求关联的 I/O 操作,框架将调用驱动程序的 OnCancel 回调函数,以便驱动程序可以取消 I/O 请求。

如果司机拥有请求的时间相对较长,则应调用 MarkCancelable 。 例如,驱动程序可能必须等待设备响应,或者可能需要等待较低的驱动程序完成驱动程序在收到单个请求时创建的一组请求。

如果驱动程序未调用 MarkCancelable,或者驱动程序在调用 MarkCancelable 后调用 IWDFIoRequest::UnmarkCancelable,则驱动程序不知道取消,因此会像通常一样处理请求。

调用 IsCanceled

如果驱动程序尚未调用 MarkCancelable 来注册 OnCancel 回调函数,它可以调用 IWDFIoRequest2::IsCanceled 来确定 I/O 管理器是否已尝试取消 I/O 请求。 如果 IsCanceled 返回 TRUE,则驱动程序应取消请求。

例如,如果驱动程序未为收到的请求调用 MarkCancelable,则接收大型读取或写入请求的驱动程序可能会调用 IsCanceled。如果驱动程序未针对收到的请求调用 MarkCancelable,则驱动程序可能会在驱动程序的 I/O 目标完成每个较小的请求后调用 IsCanceled

取消请求

取消 I/O 请求可能涉及以下任何一项:

  • 停止正在进行的 I/O 操作。

  • 不将请求转发到 I/O 目标。

  • 调用 IWDFIoRequest::CancelSentRequest 以尝试取消驱动程序之前已提交到 I/O 目标的请求。

如果驱动程序取消了驱动程序从框架收到的请求对象的 I/O 请求,则驱动程序必须始终通过调用 IWDFIoRequest::CompleteIWDFIoRequest::CompleteWithInformation 来完成请求,并使用 completionStatus 参数HRESULT_FROM_WIN32 (ERROR_OPERATION_ABORTED) 。 (如果驱动程序调用 IWDFDevice::CreateRequest 来创建请求对象,驱动程序将调用 IWDFObject::D eleteWdfObject 而不是完成 request.)