WinCE內(nèi)存管理報告
1. Windows CE支持虛擬內(nèi)存動態(tài)分配(virtual memory allocation),局部和單獨的堆空間(Local and separate heaps),甚至內(nèi)存映射文件(memory_mapped files,memory mapping simplifies file access. Instead of using a system-maintained pointer to write to the file, you can write directly to memory.)
2. Windows CE環(huán)境下ROM和RAM的使用和我們平時的PC機有所不同。RAM被分為 兩個區(qū)域:程序區(qū)(proram memory),也叫系統(tǒng)堆(system heap),和對象存儲(object store)。
l 對象存儲可以被看作類似于一個永久的虛擬RAM磁盤。在Pocket PC上,當我們關(guān)閉顯示屏后,系統(tǒng)實際上并沒有真正斷電,而是進入一個低功耗的睡眠狀態(tài)(由主電池來供電)。當我們按下后面的Reset按鈕后,Windows CE內(nèi)核在RAM中尋找最近一次創(chuàng)建的對象存儲,如果找到的話,就是用這個對象存儲重新啟動。
l RAM的另一個區(qū)域是程序區(qū)。這個區(qū)域就像PC機的RAM一樣。它存放所運行程序的堆和棧的空間。對象存儲和程序區(qū)的界限是可移動的。在低內(nèi)存的情況下,系統(tǒng)會請求用戶把部分可用的存儲對象空間提供給運行程序使用,以滿足程序運行的RAM需要。
u PC機上,ROM用來存儲BIOS,通常是64-128K。在WindowCE系統(tǒng)中,ROM用來存儲整個操作系統(tǒng)以及和OS綁定的應(yīng)用程序,大小可以4-32M不等。因此,WinCE下的ROM就像一個很小的只讀硬盤一樣。
u 在WinCE OS中,ROM_based程序可以被指定位就地執(zhí)行(Excute in Place)。也就是說,它們直接從ROM中執(zhí)行而不是先載入RAM然后再執(zhí)行。這樣不僅可以節(jié)省寶貴的Ram資源,而且程序啟動更快。不在ROM中的程序(在對象存儲空間里的或者是在Flash內(nèi)存中的)不能原地執(zhí)行。
3. 虛擬內(nèi)存。OS使用微處理的內(nèi)存管理單元實時地把虛擬地址轉(zhuǎn)換到物理地址。
u 分頁內(nèi)存(Paged Memory)。在WinCE OS下,一頁是1K或者4K,取決于微處理芯片。Intel 的ARM,一頁是4K。
u 虛擬頁面有三種狀態(tài):未用的(free),保留的(reserved)和占用的(committed)。一個free的頁面,顧名思義就是可以被分配的。一個reserved頁面就是已經(jīng)被預(yù)定的,所以他的虛擬地址空間不能再分配給操作系統(tǒng)和這個進程的另一個線程。它的地址還未映射到物理空間。一個committed頁就是已經(jīng)被一個程序保留了并且已經(jīng)直接映射到了一個物理地址空間。
4.WinCE地址空間
u 為所有的應(yīng)用程序?qū)崿F(xiàn)單個的2GB的虛擬地址,但是每個應(yīng)用程序的內(nèi)存空間都是受保護的,以保證其他應(yīng)用程序不能訪問。從最低的虛擬地址空間開始分為33個slot,每個slot32M。每個slot被分配為當前運行的進程。Slot 0中存放的當前激活的進程。當winCE在進程間切換時,它就重新映射地址空間,把老進程移出,新進程移進slot 0。這個任務(wù)是通過操作微處理器的頁轉(zhuǎn)換表來迅速完成的。
u 33個slot以上地址區(qū)域是為OS和映射內(nèi)存映射文件保留的。和windows XP一樣,winCE也保留了最低的64K地址空間,任何進程都不能訪問。
5.查詢系統(tǒng)內(nèi)存。
u GetSystemInfo(LPSYSTEM_INFO)
u GlobalMemoryStatus(LPMEMORYSTATUS)(paging files are not supported under windows CE)
6.各種內(nèi)存分配方式
u 首先是Virtualxxxx函數(shù),用來預(yù)留,提交和釋放虛擬內(nèi)存頁。然后是堆API。堆使用該應(yīng)用程序管理的保留內(nèi)存空間區(qū)域。堆有兩種:缺省的局部堆和獨立堆。堆API下來是靜態(tài)數(shù)據(jù),這些數(shù)據(jù)塊由編譯器定義并且在載入時自動分配。最后是棧,它存放應(yīng)用程序中每個函數(shù)的局部變量。
u wince不支持全局堆。因此全局堆API,wince都不支持。
u 在wince中減少內(nèi)存使用的關(guān)鍵是選擇恰當?shù)膬?nèi)存分配策略。
6.1 虛擬內(nèi)存
它是內(nèi)存類型中最基本的。系統(tǒng)可以調(diào)用虛擬內(nèi)存API來為其他內(nèi)存類型分配空間,比如堆,棧。VirtualAlloc,VirtualFree,VirtualResize函數(shù)直接在這個應(yīng)用程序的虛擬內(nèi)存空間里操作虛擬內(nèi)存頁。可以使用這些函數(shù)預(yù)留,提交和是否物理內(nèi)存。(以頁為單位的,舍入到頁的界限)
6.2 堆
顯然,以頁為單位分配內(nèi)存對于大多數(shù)程序是低效的。而堆就可以以字節(jié)為單位來申請和釋放內(nèi)存。粒度比虛擬內(nèi)存函數(shù)要?。ㄖ辽?字節(jié))。系統(tǒng)會隨著所運行程序的需求自動增長堆的大小。當堆中的一些塊被釋放后,系統(tǒng)檢查看是否整個頁都被釋放了,如果是的話,這個頁就被decommit。由于在一個堆上不斷地allocate和free,這個堆很可能被分割為一些碎片,或者有可能這個堆幾乎是空的,但是系統(tǒng)還是不能從這個堆中釋放 a page,除非它全空。
u Local Heap。每個應(yīng)用程序在啟動時都會創(chuàng)建一個缺省的堆??梢允褂肔ocalAlloc,LocalFree和LocalRealloc函數(shù)操作這個堆。
u Separate Heaps。為了避免把堆分割成很多碎片,如果在一段時間里需要一塊連續(xù)的塊空間的話,更好的方法是創(chuàng)建一個單獨的堆。實際申請空間時才映射物理地址空間,并不才創(chuàng)建時就保留或者提交任何內(nèi)存。Destroy這個堆時并不要求里面的數(shù)據(jù)塊都釋放了。
6.3棧
缺省一個棧空間最大是58K。當??臻g逐漸變小時,系統(tǒng)將進入低內(nèi)存狀態(tài)。棧空間的最大值可以在鏈接時指定。可以指定到1M。注意:
u 缺省??臻g大小也是所有其他獨立線程棧的大小。
u 如果沒有可用的物理RAM,需要棧空間的線程就會被掛起。如果在給定的一小段時間內(nèi),這個內(nèi)存需求不能得到響應(yīng),就會彈出系統(tǒng)異常。在低內(nèi)存情況下不應(yīng)該嘗試使用大量的??臻g。
6.4 靜態(tài)數(shù)據(jù)
預(yù)定義內(nèi)存塊在程序載入時為它們自動分配空間。這些塊中的數(shù)據(jù)包含了靜態(tài)申請的字符串,緩沖區(qū),和全局變量以及和這個應(yīng)用程序靜態(tài)鏈接的函數(shù)庫。Wince為一個應(yīng)用程序申請兩個RAM塊:一個用于存放Read/Write數(shù)據(jù),一個用于存放只讀數(shù)據(jù)。由于這些區(qū)域都是以頁為單位來分配內(nèi)存的,所以為了節(jié)省空間,盡量使靜態(tài)數(shù)據(jù)段接近但不能超過頁的范圍。如果在靜態(tài)數(shù)據(jù)段還有相當空間,可以把本來動態(tài)申請的一些緩沖區(qū)移到靜態(tài)數(shù)據(jù)區(qū)。有時根據(jù)具體情況可以把只讀數(shù)據(jù)區(qū)中的一些數(shù)據(jù)移到讀寫數(shù)據(jù)區(qū)。決定的方法是查看map文件。
7.在低內(nèi)存情況下WinCE如何處理應(yīng)用程序的內(nèi)存請求。
當系統(tǒng)運行需要更多的內(nèi)存,而又不能滿足的情況下,shell會自動關(guān)閉該應(yīng)用程序。因此wince提供了一些方法來在所有正在運行的程序間分配寶貴的內(nèi)存資源。
u WM_HIBERNATE消息。OS首先向非活動狀態(tài)的程序發(fā)送此消息,請求它們在不破壞各自內(nèi)在狀態(tài)情況下盡量釋放多的內(nèi)存,比如釋放GDI對象,緩沖數(shù)據(jù)等等。
u 內(nèi)存門檻(memory thresholds)。WinCE定義了四種內(nèi)存狀態(tài):normal, limited, low and critical。這些狀態(tài)的劃分主要取決于當前可用的內(nèi)存大小。當可用內(nèi)存很少時,系統(tǒng)首先發(fā)送WM_HIBERNATE消息,然后限制內(nèi)存申請的請求。
評論