信息
您所需的主题如下所示。但此主题未包含在此库中。

同步中断代码

下列因素使得在多处理器系统上处理硬件中断的驱动程序代码变得复杂:

  • 每当设备中断时,它会提供特定于中断的信息,而该信息是可变的,它会在设备下一次中断时被覆盖。

  • 设备在相对较高的 IRQL 上中断,并且其中断服务例程 (ISR) 可以中断其他驱动程序代码的执行。

  • ISR 必须在 DIRQL 上运行,同时还要保持驱动程序提供的自旋锁,以便 ISR 在保存可变信息时能够防止其他中断。DIRQL 可以防止当前处理器的中断,而自旋锁则可防止其他处理器的中断。

  • 由于 ISR 执行时设备不能中断,因此 ISR 必须快速运行。长时间的 ISR 执行会降低系统速度,也可能导致数据丢失。

  • ISR 和延迟的过程调用 (DPC) 例程通常都必须访问 ISR 在其中存储设备的可变数据的存储区域。这些例程必须相互同步,以便它们不会同时访问该存储区域。

由于以上这些因素,在编写处理中断的驱动程序代码时,您必须采用下列规则:

  • EvtInterruptIsr 回调函数访问可变的中断数据,例如包含中断信息的设备寄存器。

    EvtInterruptIsr 回调函数应当将可变数据移动到驱动程序定义的中断数据缓冲区中,驱动程序的 EvtInterruptDpc 回调函数或多个 EvtDpcFunc 回调函数可以访问该缓冲区。

    如果驱动程序为其中断对象提供 EvtInterruptIsrEvtInterruptDpc 回调函数,则中断数据的最佳存储位置是该中断对象的上下文空间。中断对象的回调函数可以通过使用所接收的对象句柄来访问该对象的上下文空间。

    如果驱动程序为每个 EvtInterruptIsr 回调函数提供多个 EvtDpcFunc 回调函数,您可能要将中断数据存储在各个 DPC 对象的上下文空间中。

  • 所有访问中断数据缓冲区的驱动程序代码都必须同步,以便一次只有一个例程访问该数据。

    EvtInterruptIsr 回调函数在保持中断对象的驱动程序提供的自旋锁期间,在 IRQL = DIRQL 上访问此数据缓冲区。因此,所有访问该缓冲区的例程也都必须在保持自旋锁期间在 DIRQL 上运行。(通常,中断的 EvtInterruptDpcEvtDpcFunc 回调函数是唯一必须访问该缓冲区的其他例程。)除了 EvtInterruptIsr 回调函数,所有访问中断数据缓冲区的其他例程都必须执行下列操作之一:

    这两种方法都允许 EvtInterruptDpcEvtDpcFunc 函数在保持中断的自旋锁期间在 DIRQL 上访问中断数据。DIRQL 可以防止当前处理器的中断,而自旋锁则可防止其他处理器的中断。

    如果设备支持多个中断矢量或消息,并且您希望同步驱动程序对这些中断的处理,则可以将单个自旋锁分配给所有中断对象。框架将确定这组中断的最高 DIRQL,并始终在该 DIRQL 上获取自旋锁,以便已同步的代码不会被该组中的任何中断矢量或消息中断。

  • 如果处理中断的代码中有一部分必须在 IRQL = PASSIVE_LEVEL 上运行,则 EvtInterruptDpcEvtDpcFunc 回调函数必须创建一或多个工作项,以便该代码将作为 EvtWorkItem 回调函数运行。

  • 如果在驱动程序的 EvtInterruptDpcEvtDpcFunc 回调函数之间,以及和其他与设备关联的回调函数之间保持同步非常重要,则驱动程序可以在中断的 WDF_INTERRUPT_CONFIG 结构和 DPC 对象的 WDF_DPC_CONFIG 结构中将 AutomaticSerialization 成员设置为 TRUE。此外,驱动程序也可以使用框架自旋锁。(将 AutomaticSerialization 成员设置为 TRUE 并不会将 EvtInterruptIsr 回调函数与其他回调函数同步。请使用 WdfInterruptSynchronizeWdfInterruptAcquireLock 同步 EvtInterruptIsr 回调函数,如本主题前文中所述。)

有关同步驱动程序例程的详细信息,请参阅基于框架的驱动程序的同步方法

 

 

社区附加资源

显示:
© 2014 Microsoft