正在同步處理中斷程式碼
下列因素會使處理多處理器系統上硬體中斷的驅動程式程式碼複雜:
每次裝置中斷時,它都會提供變動性中斷的特定資訊,因為下次裝置中斷時可能會覆寫它。
裝置會中斷相對較高的 IRQL 及其插斷服務常式, (ISR) 可能會中斷執行其他驅動程式程式碼。
針對 DIRQL 中斷,ISR 必須在 DIRQL 中執行,同時保存驅動程式提供的微調鎖定,如此一來,ISR 就可以在儲存變動性資訊時防止額外的中斷。 DIRQL 可防止目前的處理器中斷,而微調鎖定可防止另一個處理器中斷。
ISR 必須快速執行,因為裝置在執行 ISR 時無法中斷。 較長的 ISR 執行時間可能會讓系統變慢,或可能導致資料遺失。
ISR 和延後的程式調用 (DPC) 常式通常必須存取 ISR 儲存裝置變動資料的儲存區域。 這些常式必須彼此同步,才能同時存取儲存區域。
由於所有這些因素,您必須在撰寫處理中斷的驅動程式程式碼時,使用下列規則:
只有 EvtInterruptIsr 回呼函式會存取變動性中斷資料,例如包含中斷資訊的裝置暫存器。
EvtInterruptIsr回呼函式應該將變動性資料移至驅動程式定義的中斷資料緩衝區,驅動程式的EvtInterruptDpc回呼函式、EvtInterruptWorkItem回呼函式或多個EvtDpcFunc回呼函式可以存取。
如果您的驅動程式為其中斷物件提供 EvtInterruptDpc 或 EvtInterruptWorkItem 回呼函式,則儲存中斷資料的最佳位置是中斷物件 的內容空間。 中斷物件的回呼函式可以使用接收的物件控制碼來存取物件的內容空間。
如果您的驅動程式為每個EvtInterruptIsr回呼函式提供多個EvtDpcFunc回呼函式,您可能會在每個 DPC 物件的內容空間中儲存中斷資料。
所有存取中斷資料緩衝區的驅動程式程式碼都必須同步處理,如此一次只能有一個常式存取資料。
針對 DIRQL 中斷物件, EvtInterruptIsr 回呼函式會在 IRQL = DIRQL 存取此資料緩衝區,同時保存中斷物件的驅動程式提供的微調鎖定。 因此,存取緩衝區的所有常式也必須在 DIRQL 上執行,同時保存微調鎖定。 (一般而言,中斷的 EvtInterruptDpc 或 EvtDpcFunc 回呼函式是唯一必須存取 buffer.)
除了 EvtInterruptIsr 回呼函式之外,所有存取中斷資料緩衝區的常式都必須執行下列其中一項:
- 呼叫 WdfInterruptSynchronize 以排程可存取中斷資料緩衝區的 EvtInterruptSynchronize 回呼函式。
- 在呼叫 WdfInterruptAcquireLock 和 WdfInterruptReleaseLock之間放置存取中斷資料緩衝區的程式碼。
這兩種技術都允許 EvtInterruptDpc 或 EvtDpcFunc 函式在 DIRQL 存取中斷資料,同時按住中斷的微調鎖定。 DIRQL 可防止目前的處理器中斷,而微調鎖定可防止另一個處理器中斷。
如果您的裝置支援多個中斷向量或訊息,而且如果您想要同步處理驅動程式處理這些中斷,您可以將單一微調鎖定指派給多個 DIRQL 中斷物件。 架構會決定一組中斷的最高 DIRQL,而且一律會取得該 DIRQL 的微調鎖定,讓同步處理的程式碼無法被集合中的任何中斷向量或訊息中斷。
對於 被動層級中斷物件,架構會在 IRQL = PASSIVE_LEVEL呼叫驅動程式的 EvtInterruptIsr 回呼函式之前,先取得被動層級中斷鎖定。 因此,存取緩衝區的所有常式都必須取得中斷鎖定或內部同步處理緩衝區存取。 一般而言,中斷的 EvtInterruptWorkItem 回呼函式是唯一存取緩衝區的其他常式。 如需從 EvtInterruptWorkItem 回呼函式取得中斷鎖定的相關資訊,請參閱該頁面的一節。
您也可以將單一等候鎖定指派給多個被動層級中斷物件,以同步處理多個中斷向量的驅動程式處理。
如果某些處理 DIRQL 中斷的程式碼必須在 IRQL = PASSIVE_LEVEL執行,則 您的 EvtInterruptDpc 或 EvtDpcFunc 回呼函式可以建立一或多個 工作專案 ,讓程式碼以 EvtWorkItem 回呼函式的形式執行。
或者,在 KMDF 1.11 版和更新版本中,驅動程式可以呼叫 WdfInterruptQueueWorkItemForIsr來要求中斷工作專案。 (回想一下,驅動程式的 EvtInterruptIsr 回呼函式可以呼叫 WdfInterruptQueueWorkItemForIsr 或 WdfInterruptQueueDpcForIsr,但不能同時呼叫兩者。)
如果請務必將驅動程式的EvtInterruptDpc和EvtDpcFunc回呼函式彼此同步,以及與裝置相關聯的其他回呼函式同步處理,您的驅動程式可以在中斷的WDF_INTERRUPT_CONFIG結構和 DPC 物件的WDF_DPC_CONFIG結構中,將AutomaticSerialization成員設定為TRUE。 或者,驅動程式可以使用 架構微調鎖定。 (將 AutomaticSerialization 成員設定為 TRUE 並不會與其他回呼函式同步 處理 EvtInterruptIsr 回呼函式。使用 WdfInterruptSynchronize 或 WdfInterruptAcquireLock 來同步 處理 EvtInterruptIsr 回呼函式,如本主題先前所述。)
如需同步處理驅動程式常式的詳細資訊,請參閱 Framework-Based驅動程式的同步處理技術。