I/O 请求的调度方法

当驱动程序调用 WdfIoQueueCreate 来创建 I/O 队列时,它会为队列指定调度方法。 框架提供三种调度方法: 顺序并行手动。 驱动程序可以为任何 I/O 队列(包括设备 的默认 I/O 队列)指定任何这些调度方法。

驱动程序通过在队列的WDF_IO_QUEUE_CONFIG结构中指定 WDF_IO_QUEUE_DISPATCH_TYPE类型的值来设置队列的 调度 方法。

有关每个调度方法的示例用法,请参阅 I/O 队列的示例用法

顺序调度

如果驱动程序或设备一次只能处理来自队列的一个 I/O 请求,则应将设备的 I/O 队列设置为使用 顺序调度,这也称为 同步调度。 通过这种类型的调度,框架一次向驱动程序发送一个请求。 在驱动程序 完成取消重新排队 上一个请求之前,框架不会传递下一个请求。

框架将请求传递给驱动程序的请求 处理程序之一后,驱动程序将 处理请求。 如果驱动程序将请求转发到 常规 I/O 目标,它通常会调用 I/O 目标对象的同步方法之一。 有关这些方法的详细信息,请参阅 以同步方式发送 I/O 请求。 驱动程序必须最终 完成取消 它从 I/O 队列接收的每个请求。

已为顺序调度设置 I/O 队列的驱动程序可以调用 WdfIoQueueRetrieveNextRequestWdfIoQueueRetrieveRequestByFileObject ,以便在最后一个接收的请求完成或取消之前从队列获取另一个请求。 你可能希望在函数驱动程序中执行此操作,以便驱动程序可以启动下一个硬件操作,而驱动程序的 EvtInterruptDpc 回调函数仍在处理来自上一个硬件操作的数据。

如果创建多个 I/O 队列并将其全部设置为按顺序调度,框架会按顺序调度来自每个队列的请求,但队列并行运行。 如果驱动程序或设备一次只能处理一个任何类型的请求,则必须使用具有 EvtIoDefault 回调函数的单个 I/O 队列。

并行调度

如果驱动程序和设备可以同时处理多个 I/O 请求,则可以将设备的 I/O 队列设置为使用 并行调度 ,以便驱动程序可以异步处理请求。 此调度方法也称为 异步调度

如果驱动程序将 I/O 队列设置为使用并行调度,框架会将 I/O 请求在队列中可用后立即将其传送给驱动程序。 结果是驱动程序可能必须同时处理多个请求。

每当其中一个驱动程序 的请求处理程序 收到请求时,驱动程序都必须 处理该请求 ,然后 完成 请求。 如果驱动程序将请求转发到 常规 I/O 目标,它通常会调用 I/O 目标对象的异步方法之一。 有关这些方法的详细信息,请参阅 异步发送 I/O 请求。 驱动程序必须最终 完成取消 它从 I/O 队列接收的每个请求。

使用并行调度的驱动程序可以调用 WdfIoQueueStopWdfIoQueueStopSynchronously 来暂时停止队列,然后调用 WdfIoQueueStart 以重启队列。

手动调度

如果希望驱动程序完全控制 I/O 请求的传递,则可以将设备的 I/O 队列设置为使用 手动调度,这意味着框架不会向驱动程序传递请求,除非驱动程序明确请求。

若要从手动队列获取请求,驱动程序可以在轮询队列的循环中调用 WdfIoQueueRetrieveNextRequestWdfIoQueueRetrieveRequestByFileObject 。 或者,驱动程序可以调用 WdfIoQueueReadyNotify 来注册一个回调函数,当队列中有一个或多个请求可用时框架将调用该回调函数。 框架调用回调函数后,驱动程序可以在循环中调用 WdfIoQueueRetrieveNextRequestWdfIoQueueRetrieveRequestByFileObject 以检索请求。

驱动程序从队列获取请求后,必须 处理该请求。 驱动程序必须最终 完成取消 每个请求。