完成 I/O 请求

每个基于框架的驱动程序最终都必须完成它从框架收到的每个 I/O 请求。 驱动程序通过调用请求对象的 WdfRequestCompleteWdfRequestCompleteWithInformationWdfRequestCompleteWithPriorityBoost 方法完成请求。

何时完成请求

驱动程序在确定以下情况之一为 true 时,必须完成请求:

  • 请求的 I/O 操作已成功完成。

  • 请求的 I/O 操作已启动,但在完成之前失败。

  • 请求的 I/O 操作不受支持,或在收到操作时无效,无法启动。

  • 请求的 I/O 操作已取消。

如果驱动程序通过在设备上创建 I/O 活动来为 I/O 请求提供服务,驱动程序通常会从其 EvtInterruptDpcEvtDpcFunc 回调函数调用 WdfRequestComplete

如果驱动程序收到不受支持的请求或无效请求,它通常从接收请求的请求处理程序调用 WdfRequestComplete

如果 I/O 操作被取消,驱动程序通常会从其 EvtRequestCancel 回调函数调用 WdfRequestComplete

如果驱动程序将 I/O 请求 转发I/O 目标,驱动程序在 I/O 目标完成请求后完成请求,如下所示:

  • 如果驱动程序将 I/O 请求 同步 转发到 I/O 目标,则驱动程序对 I/O 目标的调用仅在较低级别的驱动程序完成请求 (后返回,除非) 发生错误。 I/O 目标返回后,驱动程序必须调用 WdfRequestComplete

  • 如果驱动程序 以异步方式转发 I/O 请求,你将希望在较低级别的驱动程序完成请求时收到通知。 如果驱动程序注册 CompletionRoutine 回调函数,框架会在 I/O 目标完成请求后调用此回调函数。 CompletionRoutine 回调函数通常调用 WdfRequestComplete

若要注册 CompletionRoutine 回调函数,驱动程序必须先调用 WdfRequestSetCompletionRoutine ,然后才能将 I/O 请求转发到 I/O 目标。

如果在 I/O 目标完成异步转发的 I/O 请求时不需要通知驱动程序,则驱动程序不必注册 CompletionRoutine 回调函数。 相反,驱动程序可以在调用 WdfRequestSend 时设置WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET标志。 在这种情况下,驱动程序不调用 WdfRequestComplete

驱动程序无法完成它通过调用 WdfRequestCreateWdfRequestCreateFromIrp 创建的 I/O 请求。 相反,驱动程序必须调用 WdfObjectDelete 来删除请求对象,通常是在 I/O 目标完成请求之后。

例如,驱动程序可能会收到读取或写入请求,该请求的数据量大于驱动程序的 I/O 目标一次可以处理的数据量。 驱动程序必须将数据划分为多个较小的请求,并将这些较小的请求发送到一个或多个 I/O 目标。 处理这种情况的方法包括:

  • 调用 WdfRequestCreate 以创建表示较小请求的单个附加请求对象。

    驱动程序可以同步将此请求发送到 I/O 目标。 较小请求的 CompletionRoutine 回调函数可以调用 WdfRequestReuse ,以便驱动程序可以重用请求并再次将其发送到 I/O 目标。 在 I/O 目标完成最后一个较小的请求后, CompletionRoutine 回调函数可以调用 WdfObjectDelete 以删除驱动程序创建的请求对象,驱动程序可以调用 WdfRequestComplete 来完成原始请求。

  • 调用 WdfRequestCreate 以创建表示较小请求的其他几个请求对象。

    驱动程序的 I/O 目标可以异步处理这些多个较小的请求。 驱动程序可以为每个较小的请求注册 CompletionRoutine 回调函数。 每次调用 CompletionRoutine 回调函数时,它都可以调用 WdfObjectDelete 来删除驱动程序创建的请求对象。 I/O 目标完成所有较小的请求后,驱动程序可以调用 WdfRequestComplete 来完成原始请求。

提供完成信息

驱动程序完成请求后,可以选择提供其他驱动程序可以访问的一些附加信息。 例如,驱动程序可以提供为读取或写入请求传输的字节数。 若要提供此信息,驱动程序可以执行以下任一操作:

获取完成信息

若要获取有关另一个驱动程序已完成的 I/O 请求的信息,驱动程序可以:

如果驱动程序以同步方式发送 I/O 请求,则它通常在同步调用返回后调用 WdfRequestGetStatusWdfRequestGetCompletionParamsWdfRequestGetInformation 。 如果驱动程序异步发送 I/O 请求,它通常从 CompletionRoutine 回调函数中调用这些方法。

有关完成 I/O 请求的详细信息,请参阅 同步取消和完成代码