天天看點

13、Windows API 記憶體管理(3)

二、堆管理<?xml:namespace prefix = o />

    使用者使用記憶體配置設定函數配置設定的記憶體都位于堆中,是以使用堆管理函數對記憶體進行配置設定、釋放等是最為直接的方式。

    Windows系統中,每個程序都有自己的堆,每個程序的堆的數量也有所不同。Windows系統中所謂的“堆”(Heap)并不是記憶體塊,而是一種用于記憶體管理的對象,也是一種記憶體組織的形式。程序可以從屬于自己的堆上配置設定記憶體和釋放記憶體。堆包括有若幹種屬性,如堆的大小最大值可以是固定的、也可以是“可增長的”;堆上的資料内容是否可以作為代碼可執行;堆是否可連接配接存取等。

三、全局和局部記憶體管理

    32位Windows系統中并沒有區分全局堆和局部堆,Windows系統中之是以還存在着全局和局部函數的概念是為了和16位系統相相容。GlobalAlloc、LocalAlloc函數所配置設定的記憶體沒有什麼差別,記憶體配置設定的效果與HeapAlloc函數類似。但是GlobalAlloc與LocalAlloc配置設定記憶體時比HeapAlloc要慢。

    是以更推薦使用Heap函數。

四、虛拟記憶體管理

    記憶體管理的原理都由系統的記憶體管理器實作,應用程式隻能管理屬性于自己的虛拟位址空間。

    程序的虛拟位址空間記憶體頁面存在3種狀态,分别為空閑的(free)、保留的(reserved)和送出的(Committed)。

13、Windows API 記憶體管理(3)

五、記憶體配置設定的比較

使用VirtualAlloc,VirtualFree等函數進行操作,其操作的基本機關是記憶體頁面。

HeapAlloc、GlobalAlloc、LoaclAlloc在功能上沒有大的差別,都是在堆中配置設定記憶體,配置設定的記憶體不需要進行頁對齊,也不用關心分頁機制、頁面狀态、頁面屬性等内容。HeapAlloc是程式在需要配置設定記憶體時最直接的方式。這些内容由堆管理器負責。

堆記憶體管理依賴于虛拟記憶體管理。在建立堆時,HeapCreate API函數會向系統請求虛拟記憶體分頁,之後在這個堆上的記憶體配置設定實際上是在從虛拟記憶體管理中擷取的記憶體分頁上再配置設定大小任意的記憶體塊,如果在建立堆時指定了固定了堆大小,那麼在堆上配置設定記憶體塊時,其範圍不能超過設定的堆大小,堆大小一定是記憶體頁大小的整數倍。如果在建立堆時不固定堆的大小,堆管理函數會根據配置設定的請求數量,動态地向虛拟内容管理函數請求記憶體分頁。

VirtualAlloc的功能是對程序虛拟位址空間中記憶體分頁的狀态進行管理,屬于虛拟記憶體管理(以記憶體頁面為機關)的範圍。當然記憶體的配置設定也是通過改變虛拟記憶體頁面屬性來實作的,是以VirtualAlloc間接達到了配置設定記憶體的目的。堆管理器也是依賴于虛拟記憶體管理的,在收到HeapAlloc的記憶體配置設定的請求時,堆管理器會根據情況決定是否使用虛拟記憶體管理機制配置設定新的頁面,以及如何在頁面上布局配置設定的記憶體塊,從這個層次上講VirtualAlloc更為底層。

    實際上隻要虛拟記憶體管理函數将頁面屬性設定為“已送出”後,就可以在之上進行讀寫等操作。

    堆管理函數為應用程式提供了一種更靈活、更簡單的方式來管理這些“已送出”的記憶體。其好處一是配置設定更簡單,二是可以配置設定任意大小的記憶體,三是不用直接與複制的記憶體分頁機制打交道。

    标準C函數的記憶體配置設定函數則直接使用了HeapAlloc。

    HeapAlloc、GlobalAlloc、LoaclAlloc在32位系統上功能上是一緻的,但是由于Globa]_Alloc、LoaclAlloc需要相容16位系統,所需進行的判斷和處理會更多,是以GlobalAlloc、LoaclAlloc較HeapAlloc效率低。當然标準C函數malloc也是調用HeapAlloc實作的,是以其效率也必然比HeapAlloc低。

    由于HeapAlloc與VirtualAlloc功能定位上的不同,是以在效率上沒有可比性。從原理上講,HeapAlloc在配置設定記憶體時,如果堆管理器中有足夠的已送出的頁面可以使用,那麼它不需要将記憶體分頁從其他狀态改變為已送出狀态,隻需要在堆管理器中進行相關管理;如果在配置設定時沒有足夠的已送出頁面供使用,那麼還需要将虛拟記憶體分頁從其他狀态改變為已送出狀态,在有足夠的可使用的已送出頁面的情況下,再由堆管理器進行相關管理。