使用 Lookaside 清單
必須動態配置固定大小的緩衝區以執行隨選 I/O 作業的驅動程式可以使用 Ex XxxLookasideListEx 或 ExXxxLookasideList 支援例程。 在這類驅動程式初始化其外觀清單之後,操作系統會在驅動程式的 lookaside 清單中保留一些動態配置之指定大小的緩衝區,有效地保留一組可重複使用且固定大小的驅動程式緩衝區。 驅動程式的固定大小緩衝區(也稱為 專案)的格式和內容會由驅動程序決定。
例如,必須為基礎 SCSI 埠/迷你埠驅動程式設定 SCSI 要求區塊 (SRB) 的記憶體類別驅動程式會使用 lookaside 清單。 這類類別驅動程式會視需要從其外觀清單配置 SRB 的緩衝區,並將每個 SRB 緩衝區釋放回 lookaside 清單,以便在每次 SRB 傳回已完成 IRP 中的類別驅動程式時重複使用。 因為記憶體類別驅動程式無法預先決定它在任何時候必須使用多少SRB,因為驅動程式的 I/O 需求增加和下降,所以外觀清單是一種方便且經濟的方式,可管理這類驅動程式中固定大小 SRB 的緩衝區配置和解除分配。
操作系統會針對目前正在使用的所有分頁和非分頁外觀清單,動態追蹤所有清單中專案配置和解除分配的需求,以及新專案可用的系統集區。 當配置需求很高時,操作系統會增加它在每個外觀清單中保留的項目數目。 當需求再次下降時,它將剩餘的剩餘專案釋放回系統集區。
Lookaside 清單是安全線程。 Lookaside 清單具有內建同步處理功能,可讓驅動程式中多個同時執行的線程共用 Lookaside 清單。 這些線程可以從共用外觀清單安全地配置緩衝區,並將這些緩衝區釋放到清單中,而不需要驅動程序明確地同步處理這些作業。 不過,為了避免可能的外泄和數據損毀,共用查閱清單的一組線程必須明確同步處理清單的初始化和刪除。
Lookaside 清單介面
從 Windows Vista 開始, LOOKASIDE_LIST_EX 結構描述可包含分頁或非分頁緩衝區的外觀清單。 如果驅動程式提供此外觀清單的自定義 配置 和 免費 例程,這些例程會以輸入參數的形式接收私用內容。 驅動程式可以使用此內容來收集 lookaside 列表的私人數據。 例如,內容可用來計算清單動態配置和釋放的清單項目數目。 如需示範如何以這種方式使用內容的程式代碼範例,請參閱 ExInitializeLookasideListEx。
下列系統提供的例程支援LOOKASIDE_LIST_EX結構描述的 lookaside 清單:
從 Windows 2000 開始, PAGED_LOOKASIDE_LIST 結構描述包含分頁緩衝區的查閱清單。 如果驅動程式為此外觀清單提供自定義 的 Allocate 和 Free 例程,這些例程不會以輸入參數的形式接收私用內容。 基於這個理由,如果您的驅動程式只打算在 Windows Vista 和更新版本的 Windows 上執行,請考慮使用 LOOKASIDE_LIST_EX 結構,而不是針對您的外觀清單使用 PAGED_LOOKASIDE_LIST 結構。 下列系統提供的例程支援PAGED_LOOKASIDE_LIST結構描述的 lookaside 清單:
ExAllocateFromPagedLookasideList
ExInitializePagedLookasideList
從 Windows 2000 開始, NPAGED_LOOKASIDE_LIST 結構描述包含非分頁緩衝區的查閱清單。 如果驅動程式為此外觀清單提供自定義 的 Allocate 和 Free 例程,這些例程不會以輸入參數的形式接收私用內容。 同樣地,如果您的驅動程式只打算在 Windows Vista 和更新版本的 Windows 上執行,請考慮使用 LOOKASIDE_LIST_EX 結構,而不是 外觀清單的 NPAGED_LOOKASIDE_LIST 結構。 下列系統提供的例程支援NPAGED_LOOKASIDE_LIST結構所描述的 lookaside 清單:
ExAllocateFromNPagedLookasideList
ExInitializeNPagedLookasideList
實作指導方針
若要實作使用 LOOKASIDE_LIST_EX 結構的外觀清單,請遵循下列設計指導方針:
呼叫 ExInitializeLookasideListEx 以設定 lookaside 列表。 在此呼叫中,指定 lookaside 清單中的專案是要分頁或非分頁緩衝區。 如果驅動程式本身或任何傳遞其外觀清單專案的基礎驅動程式可能會存取 IRQL >= DISPATCH_LEVEL中的這些專案,請使用非分頁緩衝區。 只有當存取驅動程式的外觀清單專案一律發生在 IRQL <= APC_LEVEL時,才使用分頁緩衝區。
不論清單中的專案是分頁還是非分頁,lookaside 清單的LOOKASIDE_LIST_EX結構都必須一律位於非分頁系統記憶體中。
為了獲得更好的效能,除非配置和解除分配例程必須只針對 lookaside 列表專案進行配置和釋放,否則將 Allocate 和 Free 參數的 NULL 指標傳遞至 ExInitializeLookasideListEx。 例如,這些例程可能會記錄驅動程式使用動態配置緩衝區的相關信息。
驅動程式提供的 Allocate 例程可以將它直接接收的輸入參數 (PoolType、Tag 和 Size) 傳遞至 ExAllocatePoolWithTag 或 ExAllocatePoolWithQuotaTag 例程來配置新的緩衝區。
針對每一次對 ExAllocateFromLookasideListEx 的呼叫,請儘快呼叫 ExFreeToLookasideListEx,每當先前配置的專案不再使用時。
提供只呼叫 ExAllocatePoolWithTag 和 ExFreePool 的 Allocate 和 Free 例程,分別浪費處理器週期。 ExAllocateFromLookasideListEx 會在驅動程式將 NULL Allocate 和 Free 指標傳遞至 ExInitializeLookasideListEx 時,自動呼叫 ExAllocatePoolWithTag 和 ExFreePool。
任何驅動程式提供的 Allocate 例程都不得為分頁集區中的專案配置記憶體,以保留在非分頁的 lookaside 清單中,反之亦然。 它也必須配置固定大小的專案,因為任何後續的驅動程式呼叫 ExAllocateFromLookasideListEx 會傳回目前保留在 lookaside 清單中的第一個專案,除非清單是空的。 也就是說, 呼叫 ExAllocateFromLookasideListEx 只會在指定的 lookaside 列表是空的時,才會呼叫驅動程式提供的 Allocate 例程。 因此,每次呼叫 ExAllocateFromLookasideListEx 時,傳回的專案將完全是驅動程式只有在 lookaside 列表中所有專案都為固定大小時,才需要的大小。 驅動程式提供的 Allocate 例程不應該變更驅動程式原本傳遞至 ExInitializeLookasideListEx 的 Tag 值,因為集區標籤值中的變更會使偵錯和追蹤驅動程式的記憶體使用量變得更困難。
呼叫 ExFreeToLookasideListEx Store 之前在 lookaside 清單中配置的專案,除非清單已經滿(也就是說,清單包含系統決定的最大項目數)。 為了獲得更好的效能,驅動程式應該盡可能快速地呼叫 ExFreeToLookasideListEx,以便每次呼叫 ExAllocateFromLookasideListEx。 當司機快速將專案釋放回其外觀清單時,該驅動程式下一次呼叫 ExAllocateFromLookasideListEx 的可能性要低得多,因為動態配置新專案的記憶體會降低效能。
類似的指導方針適用於使用 PAGED_LOOKASIDE_LIST 或 NPAGED_LOOKASIDE_LIST 結構的外觀清單。