mmLockPagableCodeSection 宏 (wdm.h)
MmLockPagableCodeSection 例程會將驅動程式程式代碼的區段鎖定,其中包含一組以特殊編譯程式指示詞標示的驅動程式例程到系統空間中。
語法
void MmLockPagableCodeSection(
[in] Address
);
參數
[in] Address
指定符號位址。 此位址通常是驅動程式程式代碼區段中的驅動程式函式名稱,其標記為 #pragma alloc_text (PAGExxxx、driverfunction) 。 然後,當此函式傳回時, PAGExxxx 區段中的所有函式都保證會鎖定。
傳回值
無
備註
MmLockPagableCodeSection 會傳回作業系統用來識別此驅動程式程式代碼區段的不透明值。 如果驅動程式解除鎖定,稍後會將此不透明值傳遞至 MmLockPagableSectionByHandle (,然後重新鎖定區段) 或重新鎖定至 MmUnlockPagableImageSection。
MmLockPagableCodeSection 例程和 MmUnlockPagableImageSection (執行相反動作的例程,) 支援可執行下列動作的驅動程式:
延遲將驅動程式例程子集載入駐留記憶體,直到驅動程式裝置的傳入 I/O 要求需要這些例程來處理 IRP 為止。
當驅動程式例程完成 I/O 要求的處理時,請讓相同的驅動程式例程子集可供分頁,而且目前不會預期驅動程式裝置的其他要求。
MmLockPagableCodeSection、 mmLockPagableSectionByHandle 和 mmUnlockPagableImageSection 適用於具有下列特性的裝置和中繼驅動程式:
驅動程式具有在執行系統時可能不需要的程式代碼路徑,但如果需要,驅動程式的程式代碼必須駐留,因為它會在任意線程內容中執行,或在 IRQL >= DISPATCH_LEVEL。
驅動程式可以確切判斷何時應該載入可分頁例程,以及何時可以再次分頁。
例如,系統提供的容錯磁碟驅動程序支援建立鏡像集、等量集和磁碟區集。 不過,特定計算機只能設定鏡像集、只有等量集、只有磁碟區集,或是這三個可能選項的任意組合。 在這些情況下,系統 ftdisk 驅動程式會將明確支援鏡像、等量和磁碟區集的例程標示為屬於可分頁程式代碼區段,以減少其載入映像的大小。 在驅動程式初始化期間,只有當使用者已將磁碟設定為具有鏡像、等量或磁碟區集時,可分頁程式代碼區段才會成為駐留區段。 如果用戶動態重新分割磁碟,ftdisk 驅動程式會鎖定支持使用者要求的任何鏡像、等量或磁碟區集所需的任何其他可分頁程式代碼區段。
作為其他範例,系統提供的序列和平行驅動程式具有 DispatchCreate 和 DispatchClose 例程,這些例程會在針對獨佔 I/O 開啟特定埠,以及分別釋放開啟之埠的句柄時呼叫。 不過,序列和平行 I/O 要求是暫時的,取決於使用者目前正在執行的應用程式,以及使用者目前正在執行的應用程式選項。 在這些情況下,系統序列和平行驅動程式會藉由將許多例程標示為屬於分頁程式代碼區段的可分頁程式代碼區段,藉此減少其載入的影像大小,只有當第一個埠已針對 I/O 開啟時, DispatchCreate 例程才會成為駐留狀態。
請注意,上述每個系統驅動程式都滿足這兩個可分頁區段的準則:驅動程式具有在執行系統時可能不需要的程式代碼路徑,而且驅動程式可以確切判斷其可分頁區段的載入時機,並可再次分頁。
因為鎖定區段是昂貴的作業,如果驅動程式鎖定多個位置的可分頁程式代碼區段,請使用 MmLockPagableCodeSection 作為第一個要求。 呼叫 MmLockPagableSectionByHandle 傳遞 MmLockPagableCodeSection 所傳回的句柄,以提出後續的鎖定要求。 依句柄鎖定可大幅改善驅動程式效能,因為記憶體管理員會使用不透明傳回值來快速找出相關的區段,而不是搜尋載入的模組清單。 鎖定的區段會藉由呼叫 MmUnlockPagableImageSection 來解除鎖定。
可分頁程式代碼區段中的每個驅動程式例程都必須以下列編譯程式指示詞標示:
#pragma alloc_text(PAGExxxx, DriverRoutine)
其中 xxxx 是呼叫端可分頁區段的選擇性四個字元唯一標識碼,而 DriverRoutine 則是要在可分頁程式碼區段中包含的進入點。 關鍵詞 PAGE 和驅動程式決定的後綴最多可以有四個字元,會區分大小寫;也就是說, PAGE 必須大寫。
中 MmLockPagableCodeSection 的單一呼叫,例如,驅動程式的 DispatchCreate 例程會導致整個區段,其中包含標示為相同 PAGExxxx 標識符的每個驅動程式例程,在系統空間中鎖定。
某些類型的驅動程式例程無法成為任何驅動程式可分頁區段的一部分,包括下列各項:
永遠不要讓ISR可分頁。 即使裝置未使用,設備驅動器還是可能會收到假性中斷,特別是當插斷向量可以共用時。 一般而言,即使驅動程式可以明確停用其裝置上的中斷,ISR 不應該設為可分頁。
如果驅動程式無法在 DPC 排入佇列時控制 DPC,例如任何可能從 ISR 排入佇列的 DpcForIsr 或 CustomDpc 例程,請勿讓 DPC 例程可分頁。 一般而言,在 IRQL >= DISPATCH_LEVEL執行的驅動程式例程,而且可以在任意線程內容中呼叫,或回應隨機外部事件,不應設為可分頁。
絕對不要讓 DispatchRead 或 DispatchWrite 例程可在任何可能屬於系統分頁 I/O 路徑的驅動程式中分頁。 可能包含系統頁面檔案之磁碟的驅動程序必須具有 在 系統執行時所在的 DispatchRead 和 DispatchWrite 例程,如同這類磁碟驅動程式上分層的所有驅動程式一樣。
請注意,以編譯程式指示詞標示的可分頁區段中的例程 #pragma alloc_text (PAGExxxx,...) 不同於以編譯程式指示詞標示的例程 ,#pragma alloc_text (INIT, ...) 。 INIT 區段中的例程無法分頁,如果驅動程式有,則會在驅動程式從 DriverEntry 或 重新初始化 例程傳回時立即捨棄。
記憶體管理員會在任何驅動程式的可分頁區段上維護內部鎖定計數。 呼叫 MmLockPagableCodeSection 遞增此計數,而倒數 MmUnlockPagableImageSection 會遞減計數。 除非此計數為零,否則無法分頁驅動程式的可分頁區段。
如需建立可分頁程式代碼區段的詳細資訊,請參閱 讓驅動程式可分頁。
規格需求
需求 | 值 |
---|---|
目標平台 | 桌面 |
標頭 | wdm.h (包括 Wdm.h、Ntddk.h、Ntifs.h) |
程式庫 | NtosKrnl.lib |
Dll | NtosKrnl.exe |
IRQL | <=APC_LEVEL |