使用計時器物件
下圖說明如何使用通知計時器來設定作業的逾時間隔,然後等候其他驅動程式常式處理 I/O 要求。
如上圖所示,驅動程式必須提供計時器物件的儲存體,此物件必須透過呼叫 KeInitializeTimer 來初始化,並具有此儲存體的指標。 驅動程式通常會從其 AddDevice 常式進行此呼叫。
在特定執行緒的內容中,例如驅動程式建立的執行緒或要求同步 I/O 作業的執行緒,驅動程式可以等候其計時器物件,如上圖所示:
執行緒會使用計時器物件的指標和指定的 DueTime 值呼叫KeSetTimer,以 100 奈秒為單位表示。 DueTime的正值會指定計時器物件應該從核心的計時器佇列中移除並設定為 Signaled 狀態的絕對時間。 DueTime的負值會指定相對於目前系統時間的間隔。
請注意,在系統執行緒中執行的執行緒 (或驅動程式常式) 傳遞 DPC 物件的 Null 指標, (在說明使用 CustomTimerDpc 常式的計時器和 DPC 物件進行自訂TimerDpc 常式 時,) 在呼叫 KeSetTimer 時呼叫 KeSetTimer ,而不是佇列 CustomTimerDpc 常式。
執行緒會使用計時器物件的指標呼叫 KeWaitForSingleObject ,這會讓執行緒進入等候狀態,而計時器物件位於核心的計時器佇列中。
指定的 DueTime 到期。
核心會取消佇列計時器物件、將它設定為 Signaled 狀態,並將執行緒的狀態從等候變更為就緒。
核心會在處理器可用時立即分派執行執行緒:也就是說,沒有其他優先順序較高的執行緒處於就緒狀態,而且沒有核心模式常式可在較高的 IRQL 執行。
在 IRQL > = DISPATCH_LEVEL執行的驅動程式常式可以使用具有相關聯 DPC 物件的計時器物件來逾時要求,以將驅動程式提供的 CustomTimerDpc 常式排入佇列。 只有在非bitrary 執行緒內容內執行的驅動程式常式可以等候計時器物件上的非零間隔,如上圖所示。
就像其他執行緒一樣,驅動程式建立的執行緒是由核心執行緒物件表示,這也是發送器物件。 因此,驅動程式不需要其驅動程式建立的執行緒使用計時器物件,主動將自己放入指定間隔的等候狀態。 相反地,執行緒可以使用呼叫端提供的間隔來呼叫 KeDelayExecutionThread 。 如需這項技術的詳細資訊,請參閱 輪詢裝置。
DriverEntry、Reinitialize和Unload常式也會在系統執行緒內容中執行,因此驅動程式可以使用驅動程式初始化的計時器物件或KeDelayExecutionThread來呼叫KeWaitForSingleObject。 如果裝置驅動程式必須在初始化期間等候裝置更新狀態,則裝置驅動程式可以呼叫 KeStallExecutionProcessor , (最好小於 50 微秒) 。
不過,較高層級的驅動程式通常會在其 DriverEntry 和 重新初始化 常式中使用另一個同步處理機制,而不是使用計時器物件。 較高層級的驅動程式應該一律設計成將本身分層至特定類型或類型裝置的任何較低層級驅動程式。 因此,如果驅動程式在計時器物件上等候,或呼叫 KeDelayExecutionThread ,則較高層級的驅動程式通常會變慢載入,因為這類驅動程式必須等候夠長的時間,以容納最慢支援的裝置。 另請注意,這類等候的「安全」但最小間隔很難判斷。
同樣地,PnP 驅動程式不應該等待其他動作發生,而是應該使用 PnP 管理員的 通知 機制。