共用方式為


同步處理中斷程式碼

下列因素會使處理多處理器系統上硬體中斷的驅動程式程式代碼複雜化:

  • 每次裝置中斷時,它都會提供中斷特定的資訊,這些資訊是暫時性的,因為下次中斷時可能會被覆蓋。

  • 裝置在相對較高的 IRQL 中斷時,其中斷服務例程(ISR)可能會暫停其他驅動程式代碼的執行。

  • 若為 DIRQL 中斷,ISR 必須在 DIRQL 執行時持有驅動程式提供的自旋鎖,讓 ISR 可以在儲存揮發性資訊時防止其他中斷。 DIRQL 可防止目前的處理器中斷,而自旋鎖可防止另一個處理器中斷。

  • ISR 必須快速執行,因為裝置在執行ISR時無法中斷。 長時間的ISR運行時間可能會使系統變慢,或可能導致資料遺失。

  • ISR 和延遲程序呼叫 (DPC) 例行程序通常都必須存取存放裝置易失性數據的儲存區域。 這些例程必須彼此同步,這樣它們就不會同時存取儲存區域。

由於這些因素,您必須在撰寫處理中斷的驅動程式程式代碼時,使用下列規則:

  • 只有 EvtInterruptIsr 回呼函式會存取揮發性中斷數據,例如包含中斷資訊的裝置緩存器。

    EvtInterruptIsr 回呼函式應將揮發性數據移至驅動程式定義的中斷數據緩衝區,而驅動程式 EvtInterruptDpc 回呼函式、EvtInterruptWorkItem 回呼函式,或多個 EvtDpcFunc 回呼函式可以存取。

    如果您的驅動程式提供 EvtInterruptDpcEvtInterruptWorkItem 其中斷物件的回呼函式,則儲存中斷數據的最佳位置是中斷對象的 內容空間。 中斷物件的回呼函式可以使用接收的物件句柄來存取物件的上下文空間。

    如果您的驅動程式為每個 EvtInterruptIsr 回呼函式提供多個 EvtDpcFunc 回呼函式,您可能會在每個 DPC 對象的內容空間中儲存中斷數據。

  • 所有存取中斷數據緩衝區的驅動程式程式代碼都必須同步處理,這樣一次只能有一個例程存取數據。

    對於 DIRQL 中斷物件,EvtInterruptIsr 回呼函式會在 IRQL = DIRQL 存取這個資料緩衝區,並持有中斷物件的驅動程式所提供的旋轉鎖。 因此,存取緩衝區的所有例程也必須在 DIRQL 執行,同時持有自旋鎖。 (一般而言,中斷的 EvtInterruptDpcEvtDpcFunc 回呼函式是唯一必須存取緩衝區的其他例程。)

    存取中斷數據緩衝區的所有例程,除了 EvtInterruptIsr 回呼函式之外,都必須執行下列其中一項:

    這兩種技術都允許 EvtInterruptDpcEvtDpcFunc 函式在 DIRQL 上存取中斷數據,同時持有中斷的旋轉鎖。 DIRQL 可防止目前的處理器中斷,而自旋鎖可防止另一個處理器中斷。

    如果您的裝置支援多個中斷向量或訊息,而且您希望將驅動程式對這些中斷的處理進行同步,您可以將單一的自旋鎖指派給多個 DIRQL 中斷物件。 架構會決定在一組中斷中最高的 DIRQL,並且始終在該 DIRQL 獲取自旋鎖,從而使同步程式碼不會被該集合中的任何中斷向量或訊息中斷。

    針對 被動層級中斷物件,架構會在 IRQL = PASSIVE_LEVEL 呼叫驅動程式的 EvtInterruptIsr 回呼函式之前,先取得被動層級中斷鎖定。 因此,存取緩衝區的所有例程都必須取得中斷鎖,或者在內部同步緩衝區的存取。 一般而言,中斷的 EvtInterruptWorkItem 回呼功能是唯一會存取緩衝區的其他例程。 如需有關從 EvtInterruptWorkItem 回呼函式中獲得中斷鎖定的資訊,請參閱該頁面的「備註」一節。

    您也可以將單一等候鎖定指派給多個被動層級中斷物件,以便您的驅動程序能同步處理多個中斷向量。

  • 如果您的某些處理 DIRQL 中斷的程式碼必須在 IRQL = PASSIVE_LEVEL 執行,那麼透過 EvtInterruptDpcEvtDpcFunc 回呼函式,可以建立一個或多個 工作專案,讓程式碼以 EvtWorkItem 回呼函式的形式執行。

    或者,在 KMDF 1.11 版和更新版本中,驅動程式可以呼叫 WdfInterruptQueueWorkItemForIsr來要求中斷工作專案。 (回想一下,驅動程式的 EvtInterruptIsr 回呼函式可以呼叫 WdfInterruptQueueWorkItemForIsrWdfInterruptQueueDpcForIsr,但不能同時呼叫兩者。

  • 如果要同步驅動程式的 EvtInterruptDpcEvtDpcFunc 回呼函式,以及與裝置相關的其他回呼函式,您的驅動程式可以在中斷的 WDF_INTERRUPT_CONFIG 結構中,及 DPC 物件的 WDF_DPC_CONFIG 結構中,將 AutomaticSerialization 成員設定為 TRUE。 或者,驅動程式可以使用 架構自旋鎖。 (將 AutomaticSerialization 成員設定為 TRUE 時,不會將 EvtInterruptIsr 回呼函式與其他回呼函式同步。應使用 WdfInterruptSynchronizeWdfInterruptAcquireLock 來同步 EvtInterruptIsr 回呼函式,如本主題先前所述。)

如需同步驅動程式常規的詳細資訊,請參閱 驅動程式的 Framework-Based 同步技術