同步處理範例
下列範例說明迷你驅動程式在同步處理方面需要執行的動作,並包含不應該使用同步處理的範例:
範例 1:具有運作中 ISR 的 Minidriver
如果開啟數據流類別同步處理,則會使用 KeSynchronizeExecution 在引發 IRQL 時呼叫所有 minidriver 進入點,這表示當迷你驅動程式執行其程式代碼時,適配卡的 IRQ 層級和所有較低的 IRQ 層級都會遮罩。 因此,迷你驅動程序必須在此模式中只執行少量的工作。
迷你驅動程式不應該在引發 IRQL 時執行通常需要超過 10 到 20 微秒的程式代碼。 如果您使用 stream.sys的偵錯組建,數據流類別會記錄在引發 IRQL 所花費的時間量,並判斷驅動程式是否花費太多時間。 如果 minidriver 只需要程式設計硬體 DMA 註冊要求,或只需要在其 ISR 中讀取埠,通常可以接受在引發 IRQL 執行其所有處理。
如果 minidriver 需要執行超過幾微秒的處理,例如透過 PIO 傳輸數據的迷你驅動程式,minidriver 應該使用 StreamClassCallAtNewPriority 來排程DISPATCH_LEVEL回呼。 在回呼中,minidriver 最多可能需要 1/2 到 1 毫秒才能執行其處理。 在此模式中,有一件事要記住的是,DISPATCH_LEVEL回呼 不會 與ISR同步。
如果迷你驅動程式在回呼和ISR期間存取資源(例如埠或佇列)時,硬體保持穩定,則這種同步處理不足並不成問題。 但是,如果不穩定可能是問題,minidriver 必須使用 StreamClassCallAtNewPriority 來排程高優先順序回呼,其中DISPATCH_LEVEL回呼會觸及與 ISR 所使用的資源分享的資源。
請注意,HIGH 優先順序回呼相當於呼叫 KeSynchronizeExecution。 KeSynchronizeExecution 需要 minidriver 參考 StreamClassCallAtNewPriority 不具有的數個參數,但一般而言,這兩個結果會產生相同的行為。
如果 minidriver 偶爾只需要執行超過 1/2 到 1 毫秒的程式代碼,或偶爾需要在PASSIVE_LEVEL呼叫服務(例如在初始化時間),則可以 使用 StreamClassCallAtNewPriority 設定為 LOW 優先順序來取得PASSIVE_LEVEL背景工作線程。 請注意,低優先順序回呼不會與任何專案同步,而且迷你驅動程式可以接收新的要求(假設 ReadyForNextRequest NotificationType 參數擱置中)或執行低優先順序回呼時的 ISR 呼叫。
範例二:沒有ISR的Minidriver
如果已開啟數據流類別同步處理,迷你驅動程序的進入點全都會在DISPATCH_LEVEL呼叫。 迷你驅動程式最多可以處理大約 1/2 到 1 毫秒的持續時間,而不需要調整優先順序。 如果 minidriver 偶爾需要執行超過 1/2 毫秒的程式代碼,或偶爾需要在PASSIVE_LEVEL呼叫服務(例如在初始化階段),則 StreamClassCallAtNewPriority 與 LOW 優先順序的 StreamClassCallNewPriority 可用來取得PASSIVE_LEVEL背景工作線程。 請注意,低優先順序回呼不會與任何專案同步處理,而minidriver可能會在執行低優先順序回呼時收到新要求(假設 ReadyForNextRequest NotificationType 參數擱置中)。
不應該使用數據流類別同步處理時
以下是不應該使用數據流類別同步處理的情況範例。 包括:
當驅動程式經常(超過 20% 的要求時,迷你驅動程式收到的要求)需要執行超過 1 毫秒的處理,或需要經常呼叫PASSIVE_LEVEL服務,例如 Microsoft DirectDraw 服務。 使用偵錯版本的 stream.sys 時,數據流類別會判斷提示這兩個案例,並在開啟同步處理時停止。
當 minidriver 是沒有相關聯硬體的篩選條件時。 這類迷你驅動程式應該在 PASSIVE_LEVEL 執行,因為沒有任何基礎硬體可以與 同步處理,而minidriver通常會執行許多處理。 在此情況下,執行自己的同步處理比使用串流類別同步處理浪費額外負荷更容易。 如有必要,請使用 Mutex 來保護您的佇列。
同步處理程式代碼中的 Bug 通常很難找到,而且在某些環境中(例如在多處理器系統上執行的 NT 型作業系統)Bug 只有在壓力數小時後才會顯示。 根據廠商的經驗,這些不是大部分廠商具備偵錯功能或想要偵錯的項目類型。 只有熟悉撰寫完全異步 WDM 設備驅動器的驅動程式寫入器應該嘗試執行自己的同步處理。
當 minidriver 是總線上型驅動程式(例如 USB 或 1394 周邊驅動程式)時,它並不真正擔心實際硬體的同步處理,而只是在PASSIVE_LEVEL呼叫下一層的要求,並通常會在DISPATCH_LEVEL接收回呼。