設定和使用連結佇列
新的驅動程式應該使用 取消安全 IRP 佇列 架構,並偏好使用本節中所述的方法。
具有裝置專用線程的驅動程式,或是使用執行背景工作執行緒的驅動程式,例如大部分的系統 FSD,都是在連結佇列中管理自己執行時間內部佇列 IRP 的最可能類型。 所有 PnP 驅動程式,包括 WDM 驅動程式,也必須在內部排入特定 IRP 佇列,同時進行 PnP 和電源狀態轉換。
通常,這些驅動程式會設定兩次連結的相互連結的佇列;每個 IRP 都包含類型 LIST_ENTRY的成員,驅動程式可用來將目前持有的 IRP 連結成倍。 如果驅動程式設定 Singly linked interlocked 佇列,則無法重新佇列的 IRP 進行重試。
驅動程式必須在裝置初始化時設定其相互鎖定的佇列。 下圖說明兩次連結的相互連結的佇列、驅動程式必須呼叫的支援常式來設定這類佇列,以及驅動程式可以呼叫的一組ExInterlockedXxx常式,以將 IRP 插入佇列並移除 IRP。
如圖所示,驅動程式必須提供佇列本身的儲存體,並針對下列專案提供儲存體,才能設定兩次連結的相互連結的佇列:
主管微調鎖定,驅動程式必須呼叫 KeInitializeSpinLock 以初始化。 通常,當驅動程式在其 AddDevice 常式中設定裝置延伸模組 (s) 時,驅動程式會初始化其裝置物件的微調鎖定 (s) 。
佇列的清單前端,驅動程式必須藉由呼叫 InitializeListHead初始化。
大部分使用多點連結的連線佇列的驅動程式,都會在驅動程式所建立裝置物件的裝置延伸模組中提供必要的儲存空間。 如果驅動程式使用 控制器物件) 或驅動程式所配置的非分頁集區,佇列和執行微調鎖定可以改為位於控制器擴充功能中 (。
當驅動程式接受 I/O 要求時,如果 ListHead 的類型為 LIST_ENTRY,它可以藉由呼叫下列其中一個支援常式,將 IRP 插入其佇列中,如下圖所示:
ExInterlockedInsertTailList 將 IRP 放在佇列結尾
ExInterlockedInsertHeadList 將 IRP 放在佇列前端。 驅動程式通常只有在必須重試特定要求時,才會呼叫此常式。
驅動程式必須將指標傳遞至 IRP (ListEntry) ,以及 ListHead 和執行微調鎖定 (鎖定) 先前初始化的指標,傳遞給每個 ExInterlockedInsertXxxList 常式。 當驅動程式呼叫ExInterlockedRemoveHeadList來取消佇列 IRP 時,只需要ListHead和Lock的指標。 若要防止死結,驅動程式不得持有傳遞至任何ExInterlockedXxx常式的 ExecutiveSpinLock。
由於交錯佇列受到執行微調鎖定的保護,因此驅動程式可以將 IRP 插入其多工連結佇列,並以多處理器安全的方式從執行小於或等於 IRQL = DISPATCH_LEVEL 的任何驅動程式常式中移除它們。
類型 為 listHead的佇列LIST_ENTRY,如上圖所示,是一個重複連結的清單。 其中一個具有類型 為 SLIST_HEADER 的 ListHead 是循序且單向連結的清單。 驅動程式會呼叫 ExInitializeSListHead,以初始化循序連結的相互連結佇列的 ListHead。
從未重試 I/O 作業的驅動程式可以使用 ExInterlockedPushEntrySList 和 ExInterlockedPopEntrySList ,在循序且連續連結的佇列佇列中管理 IRP 的佇列。 任何使用此型別的間鎖佇列驅動程式也必須為 類型為 SLIST_HEADER 和 ExecutiveSpinLock 的 ListHead 提供固定儲存體, 如上圖所示。 它必須先初始化微調鎖定並設定其佇列,再呼叫 ExInterlockedPushEntrySList ,以將初始專案插入其佇列中。