共用方式為


設定和使用裝置佇列

驅動程式會藉由在驅動程式或裝置初始化呼叫 KeInitializeDeviceQueue 來設定裝置佇列物件。 啟動其裝置之後,驅動程式會呼叫 KeInsertDeviceQueueKeInsertByKeyDeviceQueue,將 IRP 插入此佇列。 下圖說明這些呼叫。

設定和使用裝置佇列。

如圖所示,驅動程式必須提供裝置佇列物件的記憶體,該對象必須是常駐。 設定裝置佇列物件的驅動程式通常會在驅動程式所建立裝置對象的 裝置擴充 功能中提供必要的儲存空間,但如果驅動程式使用 控制器物件 或驅動程式所配置的非分頁集區,則儲存設備可以在控制器擴充功能中。

如果驅動程式在裝置擴充功能中提供裝置佇列物件的記憶體,則會在建立裝置對象之後,以及在啟動裝置之前呼叫 KeInitializeDeviceQueue 。 換句話說,驅動程式可以從 其 AddDevice 例程或處理 PnP IRP_MN_START_DEVICE 要求時初始化佇列。 在對 KeInitializeDeviceQueue 的呼叫中,驅動程式會將指標傳遞給它提供給裝置佇列物件的記憶體。

啟動其裝置之後,驅動程式可以呼叫 KeInsertDeviceQueue 將 IRP 插入其裝置佇列,其會將 IRP 放在佇列尾端,或 KeInsertByKeyDeviceQueue,這會根據驅動程式決定 的 SortKey 值將 IRP 放入佇列中,如下圖所示。

每個支援例程都會傳回布爾值,指出 IRP 是否插入佇列。 如果佇列目前是空的(Not-Busy),這些呼叫也會將裝置佇列物件的狀態設定為 Busy。 不過,如果佇列是空的 (Not-Busy), 則 KeInsertXxxDeviceQueue 例程都不會將 IRP 插入佇列中。 相反地,它會將裝置佇列物件的狀態設定為 Busy 並傳回 FALSE。 由於 IRP 尚未排入佇列,因此驅動程式必須將它傳遞給另一個驅動程式例程,以便進一步處理。

設定補充裝置佇列時,請遵循下列實作指導方針:

當呼叫 KeInsertXxxDeviceQueue 返回 FALSE 時,呼叫者必須將嘗試排入佇列的 IRP 提交給其他驅動程式程序進行進一步處理。 不過, 對 KeInsertXxxDeviceQueue 的呼叫會將裝置佇列物件的狀態變更為 Busy,因此除非驅動程式先呼叫 KeRemoveXxxDeviceQueue ,否則傳入的下一個 IRP 會插入佇列中。

當裝置佇列物件的狀態設定為 [忙碌] 時,驅動程式可以呼叫下列其中一個支援例程,將 IRP 從佇列中取出以便進一步處理,或者將狀態重設為 Not-Busy。

呼叫任何這些例程,從為空但忙碌的裝置佇列中移除項目,會將佇列狀態變更為「非忙碌」。

每個裝置佇列物件都受到內建的執行緒旋轉鎖保護(未顯示在 使用裝置佇列物件 圖中)。 因此,驅動程式可以將 IRP 插入佇列,並以多處理器安全的方式從任何以小於或等於 IRQL = DISPATCH_LEVEL 執行的驅動程式例程中移除它們。 由於此 IRQL 限制,驅動程式無法從其在 DIRQL 執行的 ISR 或 SynchCritSection 例程呼叫任何 KeXxxDeviceQueue 例程。

如需詳細資訊,請參閱 管理硬體優先順序自旋鎖。 如需特定支援例程的 IRQL 需求,請參閱例程的參考頁面。