管理 I/O 队列

来源:互联网 发布:linux怎么退出sqlplus 编辑:程序博客网 时间:2024/05/21 06:16

启动 I/O 队列

当驱动程序调用 WdfIoQueueCreate 以创建 I/O 队列时,框架会自动启用该队列,以接收 I/O 请求并将它们传递到驱动程序。

驱动程序通常会从 EvtDriverDeviceAdd 回调函数内调用 WdfIoQueueCreate。当驱动程序的EvtDriverDeviceAdd 回调函数返回后,框架就可以开始向驱动程序传递 I/O 请求。

如果驱动程序使用的是电源管理的 I/O 队列,则在驱动程序进入其工作状态并且框架调用驱动程序的EvtDeviceD0Entry 回调函数前,框架不能开始向驱动程序传递请求。

停止和重新启动 I/O 队列

驱动程序可以调用 WdfIoQueueStopWdfIoQueueStopSynchronously 以临时阻止框架从 I/O 队列传递 I/O 请求。若要恢复 I/O 请求的传递,则驱动程序可以调用WdfIoQueueStart

如果驱动程序使用的是电源管理的 I/O 队列,则当设备离开其工作 (D0) 状态时,框架会自动停止设备的队列,当设备状态返回到 D0 时,框架会重新启动队列。

向 I/O 队列中添加请求

当系统向驱动程序发送读取、写入或设备 I/O 控制请求后,框架就会将相应请求放入到 I/O 队列中。通过调用 WdfDeviceConfigureRequestDispatching,驱动程序可以控制框架在每个队列中存储的请求类型。

通过调用 WdfRequestForwardToIoQueue,驱动程序也可以将从框架接收到的请求重新放入到队列中。

从 I/O 队列获取请求

如果驱动程序为 I/O 队列指定了顺序或并行调度方法,则它会在请求处理程序中接收请求。

如果驱动程序指定了手动或顺序调度方法,则它可以通过调用 WdfIoQueueRetrieveNextRequestWdfIoQueueRetrieveRequestByFileObject 获取请求。

搜索 I/O 请求

如果驱动程序为 I/O 队列指定了手动调度方法,则它可以使用以下步骤在队列中搜索特定的请求:

  1. 调用 WdfIoQueueFindRequest 以查找符合驱动程序指定的条件的请求。

  2. 调用 WdfIoQueueRetrieveFoundRequest 以检索 WdfIoQueueFindRequest 查找到的请求。

清除或清空 I/O 队列

清除 I/O 队列表示停止向队列中插入 I/O 请求并取消队列中已存在的任何请求。

清空 I/O 队列表示停止向队列中插入 I/O 请求,同时允许将队列中已存在的任何请求传递到驱动程序。

驱动程序通常只在其队列不是电源管理的情况下才清除或清空队列。对于电源管理的 I/O 队列,驱动程序可以提供 EvtIoStopEvtIoResume 回调函数。

如果驱动程序的某些队列不是电源管理的,则当某个队列的关联设备或 I/O 通道变得不可用时,您可能会希望清除或清空该队列。通常,除非该队列中很可能包含非常重要的信息,否则您可以清除(而非清空)它。例如,网络设备的驱动程序可能会清除其队列,而存储设备的驱动程序可能会清空其队列。

如果您希望驱动程序清除或清空 I/O 队列,则驱动程序可以调用以下队列对象方法之一:

  • WdfIoQueuePurgeWdfIoQueuePurgeSynchronously,用于停止向 I/O 队列中插入 I/O 请求和取消未处理的请求。

  • WdfIoQueueDrainWdfIoQueueDrainSynchronously,用于停止向 I/O 队列中插入 I/O 请求,同时允许传递和处理已排队的请求。

将请求从一个 I/O 队列移动到另一个 I/O 队列

当驱动程序接收到某个 I/O 请求后,您可能会希望驱动程序将该请求重新放入到不同的 I/O 队列中。为此,驱动程序会调用 WdfRequestForwardToIoQueueWdfRequestForwardToParentDeviceIoQueue,这会将该请求添加到指定队列的末尾。最后,框架会使用指定队列的调度方法再次向驱动程序传递该请求。有关将 I/O 请求从一个 I/O 队列移动到另一个 I/O 队列的详细信息,请参阅将 I/O 请求重新放入到其他队列中。

在 I/O 请求排入队列前截获它

驱动程序可以在框架将 I/O 请求放入到 I/O 队列前截获它。若要截获 I/O 请求,驱动程序必须调用 WdfDeviceInitSetIoInCallerContextCallback 以注册 EvtIoInCallerContext 回调函数。

框架会将 EvtIoInCallerContext 回调函数与设备相关联。因此,框架每次接收到系统发送到设备的请求后,它都会调用 EvtIoInCallerContext 回调函数。

通常,当 EvtIoInCallerContext 回调函数接收到某个请求后,它会对该请求进行一些初步处理。接下来,该回调函数会调用 WdfDeviceEnqueueRequest,这会将该请求返回到框架。然后,框架可以将该请求放入到适当的 I/O 队列中,就像它调用EvtIoInCallerContext 回调函数前一样。

驱动程序可能会提供 EvtIoInCallerContext 回调函数的主要原因是:驱动程序必须处理相应的 I/O 操作以支持称为既未缓冲也非直接的 I/O 的 I/O 方法。对于此 I/O 方法,驱动程序必须在 I/O 请求发起方的进程上下文中访问接收到的缓冲区。有关详细信息,请参阅在基于框架的驱动程序中访问数据缓冲区。

获取 I/O 队列属性

若要获取框架队列对象的属性,驱动程序可以调用以下方法:

  • WdfIoQueueGetDevice,用于获取队列对象所属的设备对象的句柄。

  • WdfIoQueueGetState,用于获取队列的状态信息。

0 0
原创粉丝点击