共用方式為


分配 System-Space 記憶體

這很重要

本主題中所討論的 ExAllocatePool DIS 已在 Windows 10 版本 2004 中淘汰,並已由 ExAllocatePool2ExAllocatePool3取代。 如需詳細資訊,請參閱 將已取代的 ExAllocatePool 呼叫更新為 ExAllocatePool2 和 ExAllocatePool3

驅動程式開發者可以使用其 裝置擴充功能內的系統分配空間, 做為全局儲存區,用以存放裝置特定資訊。 驅動程式只能使用核心堆疊,將少量數據傳遞至其內部例程。 某些驅動程式必須配置額外的、較大的系統空間記憶體,通常是針對I/O緩衝區。

若要配置 I/O 緩衝區空間, 要使用的最佳記憶體配置例程是 MmAllocateNonCachedMemoryMmAllocateContiguousMemorySpecifyCacheAllocateCommonBuffer(如果驅動程式的裝置使用總線主機 DMA 或系統 DMA 控制器的自動初始化模式),或 ExAllocatePoolWithTag

非分頁集區通常會在系統運行時變得碎片化,因此驅動程式的 DriverEntry 例程應該呼叫這些例程來設定驅動程式所需的任何長期 I/O 緩衝區。 除了 ExAllocatePoolWithTag之外,每個例程都會配置處理器特定界限上對齊的記憶體(由處理器的數據快取行大小決定),以提供最佳效能。

驅動程式應該盡可能經濟地配置 I/O 緩衝區,因為非分頁集區內存是有限的系統資源。 一般而言,驅動程式應該避免重複呼叫這些支援例程來要求小於PAGE_SIZE的配置,因為每個小於PAGE_SIZE的配置也隨附集區標頭,用來在內部管理配置。

在經濟上配置驅動程式緩衝區空間的秘訣

若要在經濟上配置 I/O 緩衝區內存,請注意下列事項:

  • 每次呼叫 MmAllocateNonCachedMemoryMmAllocateContiguousMemorySpecifyCache 總會傳回非分頁系統空間記憶體的整數倍,不論所要求的分配大小為何。 因此,小於頁面的要求會四捨五入為完整頁面,而頁面上的任何剩餘位元組則會浪費;呼叫 函式的驅動程式無法存取它們,而且其他內核模式程式代碼無法使用。

  • 每次呼叫 AllocateCommonBuffer 都會使用至少一個配接器對象映射寄存器,這映射至少一個字節至多一個頁面。 如需有關映射寄存器及使用共通緩衝區的詳細資訊,請參閱 Adapter Objects 和 DMA

使用 ExAllocatePoolWithTag 配置記憶體

驅動程式也可以呼叫 ExAllocatePoolWithTag,併為 PoolType 參數指定下列其中一個系統定義的 POOL_TYPE 值:

  • PoolType = NonPagedPool 用於任何不儲存在裝置擴充功能或控制器擴充功能中的物件或資源,這些物件或資源可能會在驅動程式於 IRQL > APC_LEVEL 執行時被存取。

    針對這個 PoolType 值,當指定的 NumberOfBytes 小於或等於 PAGE_SIZE 時,ExAllocatePoolWithTag 將配置所要求的記憶體數量。 否則,最後配置頁面上的任何剩餘位元組會浪費:無法讓呼叫端存取,其他內核模式程式代碼無法使用。

    例如,在 x86 上,5 KB 的配置要求會傳回兩個 4 KB 頁面。 第二頁的最後 3 KB 無法供呼叫端或其他人使用。 為了避免浪費非分頁集區,驅動程式應該以有效的方式配置多個頁面。 在此案例中,例如,驅動程式可以進行兩次分配,一次分配用於PAGE_SIZE,另一次分配用於1 KB,總共分配5 KB。

    Note 從 Windows Vista 開始,系統會自動新增額外的記憶體,因此不需要兩次分配。

  • PoolType = PagedPool,適用於總是在 IRQL <= APC_LEVEL 存取且不在檔案系統寫入路徑中的記憶體。

ExAllocatePoolWithTag 如果無法配置要求的位元組數目,則會傳回 NULL 指標。 驅動程序應該一律檢查傳回的指標。 如果其值 NULLDriverEntry 例程(或任何其他傳回 NTSTATUS 值的驅動程式例程)應該傳回STATUS_INSUFFICIENT_RESOURCES或盡可能處理錯誤狀況。