RtlCreateHeap 函式 (ntifs)
RtlCreateHeap常式會建立可供呼叫進程使用的堆積物件。 此常式會在進程的虛擬位址空間中保留空間,並為此區塊的指定初始部分配置實體儲存體。
語法
NTSYSAPI PVOID RtlCreateHeap(
[in] ULONG Flags,
[in, optional] PVOID HeapBase,
[in, optional] SIZE_T ReserveSize,
[in, optional] SIZE_T CommitSize,
[in, optional] PVOID Lock,
[in, optional] PRTL_HEAP_PARAMETERS Parameters
);
參數
[in] Flags
旗標,指定堆積的選擇性屬性。 這些選項會透過呼叫堆積函式來影響新堆積的後續存取 (RtlAllocateHeap 和 RtlFreeHeap) 。
如果未要求任何選擇性屬性,呼叫端應該將此參數設為零。
這個參數可以是下列一或多個值。
HEAP_GENERATE_EXCEPTIONS
指定系統會引發例外狀況(例如 STATUS_NO_MEMORY)來表示堆積失敗,而不是傳回 Null。
HEAP_GROWABLE
指定堆積為可成長。 如果 HeapBase 為 Null,則必須指定。
HEAP_NO_SERIALIZE
指定當堆積函數配置和釋放此堆積的記憶體時,將不會使用相互排除。 未指定 HEAP_NO_SERIALIZE 時,預設值是序列化堆積的存取。 堆積存取的序列化可讓兩個或多個執行緒同時配置和釋放相同堆積的記憶體。
[in, optional] HeapBase
指定兩個動作的其中一個:
如果 HeapBase 為非Null 值,它會指定要用於堆積之呼叫端配置記憶體區塊的基底位址。
如果 HeapBase 為 Null,則 RtlCreateHeap 會從進程的虛擬位址空間配置堆積的系統記憶體。
[in, optional] ReserveSize
如果 ReserveSize 為非零值,則會指定要為堆積保留的初始記憶體數量(以位元組為單位)。 RtlCreateHeap 會將 ReserveSize 四捨五入至下一個頁面界限,然後針對堆積保留該大小的區塊。
這個參數是選擇性的,可以是零。 下表摘要說明 ReserveSize 和 CommitSize 參數的互動。
| 值 | 結果 |
|---|---|
| ReserveSize 零、 CommitSize 零 | 64頁面一開始是針對堆積保留。 一頁一開始就會認可。 |
| ReserveSize 零、 CommitSize 非零 | RtlCreateHeap 會將 ReserveSize 設定為等於 CommitSize,然後將 ReserveSize 四捨五入到最接近的 (PAGE_SIZE * 16) 的倍數。 |
| ReserveSize 非零, CommitSize 零 | 一頁最初是針對堆積進行認可。 |
| ReserveSize 非零、 CommitSize 非零 | 如果 CommitSize 大於 ReserveSize, RtlCreateHeap 會將 CommitSize 減少為 ReserveSize。 |
[in, optional] CommitSize
如果 CommitSize 為非零值,則會指定要針對堆積認可的初始記憶體數量(以位元組為單位)。 RtlCreateHeap 會將 CommitSize 舍入至下一個頁面界限,然後針對堆積認可進程的虛擬位址空間中該大小的區塊。
這個參數是選擇性的,可以是零。
[in, optional] Lock
要當做資源鎖定使用之不透明 ERESOURCE 結構的指標。 這個參數是選擇性的,而且可以是 Null。 由呼叫端提供時,必須從非分頁集區配置結構,並藉由呼叫 ExInitializeResourceLite 或 ExReinitializeResourceLite來初始化。 如果設定了 HEAP_NO_SERIALIZE 旗標,則此參數必須是 Null。
[in, optional] Parameters
RTL_HEAP_PARAMETERS 結構的指標,其中包含建立堆積時要套用的參數。 這個參數是選擇性的,而且可以是 Null。
typedef struct _RTL_HEAP_PARAMETERS {
ULONG Length;
SIZE_T SegmentReserve;
SIZE_T SegmentCommit;
SIZE_T DeCommitFreeBlockThreshold;
SIZE_T DeCommitTotalFreeThreshold;
SIZE_T MaximumAllocationSize;
SIZE_T VirtualMemoryThreshold;
SIZE_T InitialCommit;
SIZE_T InitialReserve;
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
SIZE_T Reserved[ 2 ];
} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;
| 成員 | 值 |
|---|---|
| 長度 | RTL_HEAP_PARAMETERS 結構的大小(以位元組為單位)。 |
| SegmentReserve | 區段保留大小(以位元組為單位)。 如果未指定此值,則會使用 1 MB。 |
| SegmentCommit | 區段認可大小(以位元組為單位)。 如果未指定此值,則會使用 PAGE_SIZE * 2。 |
| DeCommitFreeBlockThreshold | 取消認可 free block 閾值(以位元組為單位)。 如果未指定此值,則會使用 PAGE_SIZE。 |
| DeCommitTotalFreeThreshold | 取消認可總可用閾值(以位元組為單位)。 如果未指定此值,則會使用65536。 |
| MaximumAllocationSize | 可從堆積配置的最大記憶體區塊大小(以位元組為單位)。 如果未指定此值,則會使用最高和最低位址(較少一頁)之間的差異。 |
| VirtualMemoryThreshold | 虛擬記憶體閾值(以位元組為單位)。 如果未指定此值,或大於最大堆積區塊大小,則會使用0x7F000 的最大堆積區塊大小。 |
| InitialCommit |
針對堆積認可的初始記憶體數量(以位元組為單位)。
必須小於或等於 InitialReserve。 如果 HeapBase 和 CommitRoutine 不是Null,這個參數會覆寫 CommitSize的值,必須是非零值;否則會予以忽略。 |
| InitialReserve |
針對堆積保留的初始記憶體數量(以位元組為單位)。
如果 HeapBase 和 CommitRoutine 不是Null,這個參數會覆寫 ReserveSize的值,必須是非零值;否則會予以忽略。 |
| CommitRoutine |
從堆積認可頁面的回呼常式。 如果此參數為非Null,則必須 nongrowable 堆積。
如果 HeapBase 為 null,則 CommitRoutine 也必須是 null。 |
| 保留 | 保留供系統使用。 驅動程式必須將此參數設定為零。 |
typedef NTSTATUS
(NTAPI * PRTL_HEAP_COMMIT_ROUTINE)(
IN PVOID Base,
IN OUT PVOID *CommitAddress,
IN OUT PSIZE_T CommitSize
);
| 參數 | 意義 |
|---|---|
| 基地 | 用於堆積之呼叫端配置記憶體區塊的基底位址。 |
| CommitAddress | 變數的指標,此變數會接收所認可之頁面區域的基底位址。 |
| CommitSize | 變數的指標,此變數會接收所配置之頁面區域的實際大小(以位元組為單位)。 |
傳回值
RtlCreateHeap 會傳回用來存取已建立之堆積的控制碼。
備註
RtlCreateHeap 會建立一個私用堆積物件,呼叫的進程可以藉由呼叫 RtlAllocateHeap來配置記憶體區塊。 初始認可大小會決定一開始為堆積配置的頁面數目。 初始保留大小會決定一開始為堆積保留的頁面數目。 保留但未認可的頁面會在進程的虛擬位址空間中建立區塊,以便擴展堆積。
如果 RtlAllocateHeap 所提出的配置要求超過堆積的初始認可大小,系統會認可堆積之實體儲存體的額外頁面,最多可達堆積的大小上限。 如果堆積是 nongrowable,則其大小上限會限制為其初始保留大小。
如果堆積是可成長,它的大小只受限於可用的記憶體。 如果 RtlAllocateHeap 要求超過目前認可的頁面大小,系統會呼叫 ZwAllocateVirtualMemory 來取得所需的記憶體,前提是實體儲存體可供使用。
此外,如果堆積是 nongrowable,則會發生絕對限制:堆積中記憶體區塊的大小上限為0x7F000 個位元組。 堆積的虛擬記憶體臨界值等於最大堆積區塊大小,或參數結構的VirtualMemoryThreshold成員值(以較小者為准)。 堆積也可能需要填補中繼資料和對齊用途的要求大小,如此一來,在4096個位元組內配置區塊的要求 (1 頁) VirtualMemoryThreshold 可能會失敗,即使堆積的大小上限大到足以包含區塊。 (需VirtualMemoryThreshold的詳細資訊,請參閱RtlCreateHeap的Parameters參數成員。 )
如果堆積已可成長,則配置大於堆積虛擬記憶體臨界值之區塊的要求不會自動失敗;系統會呼叫 ZwAllocateVirtualMemory 來取得這類大型區塊所需的記憶體。
私用堆積物件的記憶體只能由建立它的進程存取。
系統會使用來自私用堆積的記憶體來儲存堆積支援結構,因此不會有所有指定的堆積大小可供進程使用。 例如,如果 RtlAllocateHeap 要求 64 Kb (K) 的堆積大小上限為64k,則要求可能會因為系統額外負荷而失敗。
如果未指定 HEAP_NO_SERIALIZE (簡單的預設) ,堆積將會序列化呼叫進程內的存取。 當兩個或多個執行緒嘗試同時從相同堆積配置或釋放區塊時,序列化可確保互斥。 序列化的效能成本很低,但每當有多個執行緒從相同堆積配置和釋放記憶體時,就必須使用它。
設定 HEAP_NO_SERIALIZE 可排除堆積上的互斥。 若沒有序列化,使用相同堆積控制碼的兩個或多個執行緒可能會同時嘗試配置或釋放記憶體,可能會導致堆積損毀。 因此,HEAP_NO_SERIALIZE 只能在下列情況下安全地使用:
- 進程只有一個執行緒。
- 此程式有多個執行緒,但只有一個執行緒會針對特定堆積呼叫堆積函數。
- 此程式有多個執行緒,而應用程式會提供它自己的機制,以相互排除特定的堆積。
若要防止存取違規,請使用結構化例外狀況處理來保護任何寫入或讀取堆積的程式碼。 如需有關記憶體存取的結構化例外狀況處理的詳細資訊,請參閱 處理例外狀況。
規格需求
| 最低支援的用戶端 | 此常式可在 Microsoft Windows XP 及更新版本上取得。 |
| 目標平台 | 通用 |
| 標頭 | ntifs (包含 Ntifs) |
| 程式庫 | Ntoskrnl.exe .lib |
| DLL | NtosKrnl.exe (核心模式) ;Ntdll.dll (使用者模式) |
| IRQL | < DISPATCH_LEVEL |
另請參閱
意見反應
提交並檢視相關的意見反應