RtlCreateHeap 函式 (ntifs.h)
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 nonzero | RtlCreateHeap 會將 ReserveSize 設定為等於 CommitSize,然後將 ReserveSize 四捨五入到最接近的倍 (PAGE_SIZE 数 * 16) 。 |
ReserveSize 非零, CommitSize 零 | 一開始會認可堆積的頁面。 |
ReserveSize nonzero, CommitSize nonzero | 如果 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。
傳回值
RtlCreateHeap 會 傳回用來存取所建立堆積的句柄。
備註
RtlCreateHeap 會建立私人堆積物件,呼叫進程可以藉由呼叫 RtlAllocateHeap 來配置記憶體區塊。 初始認可大小決定最初為堆積配置的頁數。 初始保留大小決定最初保留給堆積的頁面數目。 保留但未認可的頁面會在堆積可以展開的進程虛擬位址空間中建立區塊。
如果 RtlAllocateHeap 所做的配置要求超過堆積的初始認可大小,則系統會認可堆積的額外實體記憶體頁面,最多可達堆積的大小上限。 如果堆積不可成長,其大小上限會限制為其初始保留大小。
如果堆積可成長,其大小只會受限於可用的記憶體。 如果 RtlAllocateHeap 的要求超過目前認可頁面的大小,系統會呼叫 ZwAllocateVirtualMemory 以取得所需的記憶體,假設實體記憶體可用。
此外,如果堆積不可成長,就會發生絕對限制:堆積中記憶體區塊的大小上限是0x7F000個字節。 堆積的虛擬記憶體臨界值等於最大堆積區塊大小,或Parameters結構之 VirtualMemoryThreshold 成員的值,以較少的值為準。 堆積可能也需要填補元數據和對齊方式的要求大小,因此要求在 4096 個字節內配置區塊 (1 個頁面) VirtualMemoryThreshold 可能會失敗,即使堆積的大小上限足以包含區塊也一樣。 (如需 VirtualMemoryThreshold 的詳細資訊,請參閱 RtlCreateHeap.) 的參數參數成員
如果堆積可成長,則配置大於堆積虛擬記憶體閾值之區塊的要求不會自動失敗;系統會呼叫 ZwAllocateVirtualMemory ,以取得這類大型區塊所需的記憶體。
私人堆積物件的記憶體只能供建立它的進程存取。
系統會使用來自私人堆積的記憶體來儲存堆積支持結構,因此並非所有指定的堆積大小都可供進程使用。 例如,如果 RtlAllocateHeap 從大小上限為 64K 的堆積要求 64 KB (K) ,則要求可能會因為系統額外負荷而失敗。
如果未指定HEAP_NO_SERIALIZE (簡單的預設) ,則堆積會在呼叫程式中串行化存取。 當兩個或多個線程嘗試同時配置或釋放相同堆積中的區塊時,串行化可確保互斥。 串行化有一小部分的效能成本,但每當多個線程配置和釋放來自相同堆積的記憶體時,都必須使用它。
設定HEAP_NO_SERIALIZE可排除堆積上的相互排除。 如果沒有串行化,使用相同堆積句柄的兩個或多個線程可能會嘗試同時配置或釋放記憶體,而可能導致堆積損毀。 因此,HEAP_NO_SERIALIZE只能在下列情況下安全地使用:
進程只有一個線程。
進程有多個線程,但只有一個線程會呼叫特定堆積的堆積函式。
進程有多個線程,而且應用程式會提供自己的機制,以排除特定堆積。
注意
若要防範存取違規,請使用結構化例外狀況處理來保護寫入或讀取堆積的任何程序代碼。 如需使用記憶體存取進行結構化例外狀況處理的詳細資訊,請參閱 處理例外狀況**。
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | Windows XP |
目標平台 | Universal |
標頭 | ntifs.h (包含 Ntifs.h) |
程式庫 | Ntoskrnl.lib |
Dll | NtosKrnl.exe (核心模式) ;Ntdll.dll (使用者模式) |
IRQL | < DISPATCH_LEVEL |