编写 ISR

生成中断的物理设备的驱动程序必须至少有一个中断服务例程 (ISR) 。 ISR 必须执行适用于设备的任何操作来消除中断,可能包括阻止设备中断。 然后,它应仅执行保存状态并将 DPC 排队的必要操作,以低于执行 ISR 的优先级 (IRQL) 完成 I/O 操作。

驱动程序的 ISR 在中断上下文中执行,由 IoConnectInterruptExSynchronizeIrql 参数指定为某个系统分配的 DIRQL

ISR 是可中断的。 具有更高系统分配 DIRQL 的另一个设备可以随时中断或高 IRQL 系统中断。

在系统调用 ISR 之前,它会获取中断的自旋锁,因此 ISR 不能在另一个处理器上同时执行。 ISR 返回后,系统会释放旋转锁。

由于 ISR 以相对较高的 IRQL 运行,因此它使用当前处理器上的等效或更低 IRQL 屏蔽中断,因此它应尽快返回控制权。 此外,在 DIRQL 上运行 ISR 会限制 ISR 可以调用的支持例程集。 有关详细信息,请参阅 管理硬件优先级

通常,ISR 执行以下常规步骤:

  • 如果导致中断的设备不受 ISR 支持,则 ISR 将立即返回 FALSE

  • 否则,ISR 会根据需要清除中断,保存所需的任何设备上下文,并将 DPC 排队以在较低的 IRQL 处完成 I/O 操作。 有关详细信息,请参阅 DPC 对象和 DPC 。 然后,ISR 必须返回 TRUE

具体而言,在不重叠设备 I/O 操作的驱动程序中,ISR 应执行以下操作:

  1. 确定中断是否为虚假中断。 如果是,请立即返回 FALSE ,以便立即调用中断设备的 ISR。 否则,请继续中断处理。

  2. 如有必要,请停止设备中断。

  3. 收集 DpcForIsr (或 CustomDpc) 例程完成当前操作的 I/O 处理所需的任何上下文信息。

  4. 将此上下文存储在 DpcForIsrCustomDpc 例程可访问的区域中,通常存储在处理当前 I/O 请求导致中断的目标设备对象的设备扩展中。

    如果驱动程序与 I/O 操作重叠,则上下文信息必须包括 DPC 例程需要完成的未完成请求计数,以及 DPC 例程完成每个请求所需的任何上下文。 如果在 DPC 运行之前调用 ISR 来处理另一个中断,则它不得覆盖 DPC 尚未完成的请求的已保存上下文。

  5. 如果驱动程序具有 DpcForIsr 例程,请使用指向当前 IRP、目标设备对象和已保存上下文的指针调用 IoRequestDpcIoRequestDpc 会将 DpcForIsr 例程排入队列,只要 IRQL 低于处理器上的DISPATCH_LEVEL即可运行。

    如果驱动程序具有 CustomDpc 例程,请使用指向与 CustomDpc 例程关联的 DPC 对象的指针 (调用 KeInsertQueueDpc,) () 指向 CustomDpc 例程完成操作所需的任何已保存上下文的指针。 通常,ISR 还会传递指向当前 IRP 和目标设备对象的指针。 只要 IRQL 低于处理器上的DISPATCH_LEVEL, 就会运行 CustomDpc 例程。

  6. 返回 TRUE 以指示其设备生成了中断。

通常,ISR 不会执行实际 I/O 处理来满足 IRP。 相反,它会停止设备中断,设置必要的状态信息,并将驱动程序的 DpcForIsrCustomDpc 排队,以执行任何必要的 I/O 处理来满足导致设备中断的当前请求。

ISR 必须在尽可能短的时间间隔内以 DIRQL 运行。 遵循此准则会增加计算机中每台设备的 I/O 吞吐量,因为以 DIRQL 运行会屏蔽系统为其分配了较小或相等 IRQL 值的所有中断。

驱动程序的中断对象的 SynchronizeIrql (在驱动程序调用 IoConnectInterrupt 时指定)确定驱动程序的 ISR 执行位置的 DIRQL。 有关详细信息,请参阅 同步对设备数据的访问