使用驱动程序创建的线程管理联锁队列

新驱动程序应优先使用 取消安全的 IRP 队列 框架,而不是本节中概述的方法。

与系统软盘控制器驱动程序一样,具有设备专用线程(而不是 StartIo 例程)的驱动程序通常在双链接互锁队列中管理自己的 IRP 队列。 当设备上需要完成工作时,驱动程序的线程会从其互锁队列中拉取 IRP。

通常,驱动程序必须管理其线程与线程与其他驱动程序例程之间共享的任何资源的同步。 驱动程序还必须通过某种方式通知其驱动程序创建的线程 IRP 已排队。 通常,线程等待存储在设备扩展中的调度程序对象,直到驱动程序的 Dispatch 例程在将 IRP 插入互锁队列后将调度程序对象设置为信号状态。

调用驱动程序的 Dispatch 例程时,每个例程都会检查输入 IRP 的 I/O 堆栈位置中的参数,如果它们有效,则将请求排入队列以供进一步处理。 对于排队到驱动程序专用线程的每个 IRP,调度例程应设置其线程在调用 ExInterlockedInsertXxxList 之前处理该 IRP 所需的任何上下文。 驱动程序在每个 IRP 中的 I/O 堆栈位置使驱动程序的线程能够访问目标设备对象的设备扩展,其中驱动程序可以与其线程共享上下文信息,因为线程从队列中删除每个 IRP。

对可取消 IRP 进行排队的驱动程序必须实现 Cancel 例程。 由于 IRP 以异步方式取消,因此必须确保驱动程序避免可能导致的争用条件。 请参阅 同步 IRP 取消 ,详细了解与取消 IRP 相关的争用条件以及避免它们的技术。

驱动程序创建的任何线程在 IRQL = PASSIVE_LEVEL 运行,并在驱动程序调用 PsCreateSystemThread 时之前设置的基本运行时优先级运行。 当从驱动程序的内部队列中删除 IRP 时,线程对 ExInterlockedRemoveHeadList 的调用会暂时将 IRQL 提升为在当前处理器上DISPATCH_LEVEL。 原始 IRQL 在从此调用返回时还原为PASSIVE_LEVEL。

任何驱动程序线程 (或驱动程序提供的工作线程回调) 都必须仔细管理运行它的 IRQL。 例如,请考虑如下事项:

  • 由于系统线程通常以 IRQL = PASSIVE_LEVEL 运行,因此驱动程序线程可能会等待内核定义的调度程序对象设置为信号状态。

    例如,设备专用线程可能会等待其他驱动程序满足某个事件并完成该线程使用 IoBuildSynchronousFsdRequest 设置的一定数量的部分传输 IRP。

  • 但是,此类设备专用线程在调用某些支持例程之前,必须在当前处理器上引发 IRQL。

    例如,如果驱动程序使用 DMA,则其设备专用线程必须在调用 KeRaiseIrql 和 KeLowerIrql 之间嵌套对 AllocateAdapterChannelFreeAdapterChannel调用,因为必须在 IRQL = DISPATCH_LEVEL调用这些例程和用于 DMA 操作的某些其他支持例程。

    请记住,StartIo 例程在DISPATCH_LEVEL运行,因此使用 DMA 的驱动程序无需从其 StartIo 例程调用 KeXxxIrql 例程。

  • 驱动程序创建的线程可以访问可分页内存,因为它在 IRQL = PASSIVE_LEVEL (自己的) 的非比特线程上下文中运行,但许多其他标准驱动程序例程在 IRQL >= DISPATCH_LEVEL 运行。 如果驱动程序创建的线程分配可由此类例程访问的内存,则必须从非分页池分配内存。 例如,如果设备专用线程分配的任何缓冲区稍后将由驱动程序的 ISR 或 SynchCritSectionAdapterControlAdapterListControlControllerControlDpcForIsrCustomDpcIoTimerCustomTimerDpc 访问,或者在更高级别的驱动程序 IoCompletion 例程中,线程分配的内存无法分页。

  • 如果驱动程序在设备扩展中维护共享状态信息或资源,则驱动程序线程 (类似于 StartIo 例程) 必须将其对物理设备以及共享数据的访问权限与访问相同设备、内存位置或资源的驱动程序的其他例程同步。

    如果线程与 ISR 共享设备或状态,则必须使用 KeSynchronizeExecution 调用驱动程序提供的 SynchCritSection 例程来对设备进行编程或访问共享状态。 请参阅 使用关键部分

    如果线程与 ISR 以外的例程共享状态或资源,则驱动程序必须使用驱动程序为其提供存储的驱动程序初始化的执行旋转锁保护共享状态或资源。 有关详细信息,请参阅 旋转锁

有关对慢速设备使用驱动程序线程的设计权衡的详细信息,请参阅 轮询设备。 另请参阅 管理硬件优先级。 有关特定支持例程的 IRQL 的具体信息,请参阅例程的参考页。