跳轉到內容

Windows 程式設計/記憶體子系統

來自 Wikibooks,開放的書籍,為開放的世界

C 程式設計師無疑會熟悉 stdlib 記憶體分配函式,例如 malloc、realloc、calloc 等。這些函式基於 Win32 API 中的許多其他函式,這些函式處理記憶體段。

Windows 記憶體

[編輯 | 編輯原始碼]

在談論記憶體子系統時,Windows 管理著 4 種不同型別的記憶體,每種型別的記憶體都有許多不同的函式來分配和釋放該記憶體。

虛擬記憶體
虛擬記憶體子系統透過頁面分配和管理記憶體。這意味著記憶體只能一次以 4 KB(或更大,取決於處理器架構)的塊分配。對於大多數應用程式來說,這是一個非常大的記憶體量,並且在大多數程式中使用虛擬記憶體函式是過度的。但是,一些程式確實需要使用整個頁面進行儲存,因此虛擬記憶體子系統可以用於此目的。
堆記憶體
堆是記憶體區域,通常佔一個頁面或頁面的幾分之一。Windows 立即為每個程序分配一個堆,稱為程序堆。stdlib 函式(如 malloc)將從此記憶體區域分配記憶體。堆可以被劃分為小的記憶體段,用於變數和動態儲存。
全域性記憶體
Windows 至少維護 1 頁記憶體,用於作為通用全域性記憶體。任何在計算機上執行的程序都可以使用全域性記憶體函式讀取或寫入此記憶體。全域性記憶體空間中的資料可以在各種程式之間共享,傳送到 Windows 剪貼簿的專案通常儲存在全域性記憶體中(以便可以將其“貼上”到任何程式中)。全域性記憶體是有限的,因此應在沒有特定需要的情況下使用。
區域性記憶體
區域性記憶體與全域性記憶體和堆記憶體都有相似之處。它是針對程序的,但記憶體由 Windows 記憶體管理器管理,而不是由程式管理。我們將在後面討論這一點。

虛擬記憶體子系統

[編輯 | 編輯原始碼]

如上所述,虛擬記憶體函式以頁為單位分配記憶體。頁面通常是 4 KB 記憶體,因此大多數應用程式不需要分配整個頁面(更不用說超過 1 個頁面)。虛擬記憶體系統本質上是其他記憶體函式用於執行其任務的原始函式基礎。例如,堆包含一個或多個頁面,堆函式將在需要時使用虛擬記憶體系統分配頁面。

當分配虛擬記憶體塊時,它們實際上並沒有被使用,它們只是被系統預留以備將來使用。其他函式需要用於將虛擬記憶體頁面分割成有用的段。由於虛擬記憶體是按頁面分配的,因此可以在虛擬記憶體上使用許多特殊分頁功能,而這些功能不能在其他型別的記憶體上使用。例如,頁面可以被鎖定(以防止讀/寫訪問),或者可以從任何特定訪問模式(讀、寫、執行)中保護它們。

也就是說,虛擬記憶體子系統中有很多函式可以使用

VirtualAlloc
VirtualFree
VirtualProtect
VirtualLock
VirtualQuery

堆記憶體

[編輯 | 編輯原始碼]

每個程式都提供了一個預設的程序堆,但一個程序可以選擇分配任意數量的其他堆,如果需要更多儲存空間。堆函式將自動管理它們的虛擬記憶體使用,因此堆可以設定為在被資料填滿時增長。如果允許堆自動增長,堆函式將在需要時自動分配額外的頁面。在 x86 架構上,堆的大小向更高的記憶體地址增長。

要使用堆記憶體,必須首先分配堆(或者必須獲得對預設堆的控制代碼)。一旦你獲得了對堆的控制代碼,你就可以將該控制代碼傳遞給記憶體分配函式,以便從該特定堆分配記憶體。

stdlib 記憶體函式(malloc、realloc、calloc、free)的使用方式與堆函式非常相似,因此熟悉 stdlib 函式的程式設計師可以透過檢查它們的名字來弄清楚許多堆函式的作用

HeapCreate
分配一個堆,並返回該堆的控制代碼。所有其他堆函式都將使用此控制代碼來唯一標識你正在訪問的特定堆。透過維護多個控制代碼,你的程式可以與多個獨立的堆進行互動。
HeapDestroy
此函式關閉堆控制代碼,並釋放堆記憶體,以便其他程序可以使用它。
GetProcessHeap
此函式返回對預設程序堆的控制代碼。每個程式在載入時都會獲得一個預設堆,在大多數應用程式中,這應該足以儲存資料項。
HeapAlloc
類似於 STDLIB 的“malloc”函式,HeapAlloc 在堆上分配儲存空間,並返回指向該空間的指標。
HeapReAlloc
類似於 STDLIB 的“realloc”函式,HeapReAlloc 重新分配變數的儲存空間以使其大小不同。
HeapFree
釋放堆上的記憶體物件。嘗試使用同一個指標訪問已釋放的記憶體會導致錯誤。

全域性記憶體

[編輯 | 編輯原始碼]

Windows 維護一定量的全域性堆記憶體。與常規程序堆相比,此記憶體有限,應僅在特別需要全域性記憶體時訪問。

當資料被寫入全域性記憶體時,你不會獲得指向該資料的指標,而是獲得該資料的控制代碼。一旦你將資料交給全域性記憶體管理器,系統就會負責它。請記住,控制代碼不是指標,也不應該用作指標。系統將管理全域性記憶體部分中的記憶體,將其在頁面之間移動,對其進行碎片整理等。資料不駐留在單個段中

GlobalAlloc
GlobalFree
GlobalDiscard
GlobalLock
GlobalUnlock
GlobalFlags
GlobalSize
GlobalHandle

區域性記憶體

[編輯 | 編輯原始碼]

在本例中,區域性記憶體不是程式在內部使用的那種儲存,例如在堆疊上以及其他位置。相反,Windows 管理一個它稱為“區域性記憶體”的特殊記憶體部分,並且它提供了一些函式來分配和管理這種特殊記憶體。區域性記憶體與全域性記憶體類似,資料被寫入區域性位置,系統返回指向該資料的控制代碼。系統將管理資料,就像在全域性記憶體中一樣。區域性函式的命名與全域性記憶體函式非常相似。但是,全域性記憶體函式和區域性記憶體函式絕不應該混用。例如,全域性記憶體控制代碼絕不應該用 LocalFree 函式關閉。

LocalAlloc
LocalFree
LocalDiscard
LocalFlags
LocalLock
LocalReAlloc
LocalUnlock
LocalHandle

下一章

[編輯 | 編輯原始碼]
華夏公益教科書