核心會定義一組稱為 核心發送器物件的物件類型,或只定義 發送器物件。 發送器物件包括定時器物件、事件物件、旗號物件、Mutex 物件和線程物件。
驅動程式可以使用調度器物件作為非任意線程內容中的同步機制,並在執行 IRQL 等於 PASSIVE_LEVEL 時進行操作。
Dispatcher 對象狀態
每個核心定義的發送器物件類型都有一種狀態,該狀態可設定為 Signaled 或 Not-Signaled。
如果一或多個線程呼叫 KeWaitForSingleObject、KeWaitForMutexObject 或 KeWaitForMultipleObjects,線程群組可以同步處理其作業。 這些函式會採用發送器對象指標做為輸入,並等到另一個例程或線程將一或多個發送器物件設定為 Signaled 狀態為止。
當線程呼叫 KeWaitForSingleObject 等候發送器物件時(或 Mutex 的 KeWaitForMutexObject ),線程就會進入 等候 狀態,直到發送器物件設定為 Signaled 狀態為止。 線程可以呼叫 KeWaitForMultipleObjects 等候任何一組發送器物件或所有物件設定為 Signaled。
每當發送器物件設定為 Signaled 狀態時,核心就會變更任何線程的狀態,等待該物件 就緒。 (同步處理定時器和同步處理事件是此規則的例外狀況;當同步處理事件或定時器收到訊號時,只有一個等候線程設定為就緒狀態。如需詳細資訊,請參閱 定時器物件和 DPC 和 事件物件。處於就緒狀態的線程會根據目前的運行時間 線程優先順序 ,以及任何具有該優先順序之線程的處理器目前可用性來排程執行。
驅動程式何時可以等候發送器物件?
一般而言,只有在至少下列其中一個情況成立時,驅動程式才能等待發送器物件設定:
驅動程式正在非任意的執行緒上下文中執行。
也就是說,您可以識別將進入等候狀態的線程。 實際上,在非bitrary 線程內容中執行的唯一驅動程式例程是 DriverEntry、 AddDevice、 Reinitialize 和 Unload 例程,以及最高層級驅動程式的分派例程。 所有這些例程都是由系統直接呼叫。
驅動程式正在執行完全同步的 I/O 要求。
也就是說,在處理 I/O 要求時,沒有驅動程式會將任何作業排入佇列,而且在驅動程式下方的驅動程式完成處理要求之前,不會傳回任何驅動程式。
此外,如果驅動程式在執行時的 IRQL 等於或高於 DISPATCH_LEVEL,則無法進入等待狀態。
根據這些限制,您必須使用下列規則:
任何驅動程式的 DriverEntry、 AddDevice、 Reinitialize 和 Unload 例程都可以等候發送器物件。
最高層級驅動程式的分派例程可以等候分派器物件。
如果 I/O 作業是同步的,則較低層級驅動程式的分派例程可以等候分派物件,例如建立、排清、關機和關閉作業、某些裝置 I/O 控制作業,以及某些 PnP 和電源作業。
較低層級驅動程式的分派例程無法等候發送器物件完成異步 I/O 作業。
在 IRQL DISPATCH_LEVEL上執行的驅動程式例程,不得等候發送器物件設定為 Signaled 狀態。
驅動程序不得嘗試等待調度器物件設置為 Signaled 狀態,以完成向分頁裝置進行或從分頁裝置接收的轉移操作。
驅動程式分派例程服務讀取/寫入要求通常無法等候發送器物件設定為 Signaled 狀態。
裝置 I/O 控制要求的分派例程可以等候分派物件被設定為 Signaled 狀態,只有當 I/O 控制程式代碼的傳輸類型為 METHOD_BUFFERED 時。
SCSI 迷你埠驅動程序不應該使用核心發送器物件。 SCSI 迷你埠驅動程序應該只呼叫 SCSI 埠驅動程序支援例程。
其他的標準驅動程式例行程序會在任意線程的上下文中執行:無論處理佇列作業還是處理裝置中斷,都是在當前執行的線程上呼叫驅動程式例行程序來完成。 此外,大部分的標準驅動程式例程會在提高的 IRQL 上執行,這些例程會在 DISPATCH_LEVEL 或(對於設備驅動程式來說)在 DIRQL 上運行。
如有必要,驅動程式可以建立裝置專用線程,以等候驅動程式的其他例程(ISR 或 SynchCritSection 例程除外)將發送器物件設定為 Signaled 狀態,並重設為 Not-Signaled 狀態。
一般指導方針是,如果您預期新的設備驅動器在 I/O 作業期間等候裝置狀態變更時,通常需要停滯超過 50 微秒,請考慮使用裝置專用線程實作驅動程式。 如果裝置驅動程式也是最高層級的驅動程式,請考慮使用 系統背景工作線程 並實作一或多個背景工作線程回呼例程。 請參閱 PsCreateSystemThread 和 使用驅動程式建立的線程管理聯結佇列。