很多實時嵌入式設備是長時間不間斷運行的,即使是少許的內存泄漏,也會積少成多,對嵌入式系統帶來災難性的影響。這幾天,我在嵌入式軟件項目中就飽嘗到這個痛苦,讓我明白到嵌入式實時系統的應用軟件也會有許多內存問題,從而導致嵌入式系統的崩潰。例如非法的內存訪問、各種死鎖以及諸如堆棧溢出、數組越界和內存泄漏等。
Windows CE作為的一種嵌入式操作系統,現正廣泛被應用。我所負責的嵌入式應用程序也是在Windows CE平臺上開發的。在進入測試階段中,我發現有一個程序模塊系統內存和CPU資源消耗急劇增加,持續增長到出現OutOfMemoryError為止,然后自動重啟。這個問題折騰到我生不如死,痛苦不堪。花了我好幾個通宵達旦的加班后,經過分析終于確認Windows CE內存泄漏是造成這次Windows CE系統崩潰的主要原因。這里與大家分享我在開發過程中遇到的內存泄漏的檢測和處理解決過程。
一.Windows CE如何進行內存分配?
為了判斷是否有內存泄露,我們首先需要了解Windows CE是如何管理內存的。許多嵌入式程序員都有一個共識,就是如果評選在Windows CE 程序中遇到多的問題,那其中一個問題一定有內存問題。
(1)什么是Windows CE內存管理
一般來說,運行Windows CE的嵌入式設備出于緊湊型的考慮內存都不大,以至于有時候有些程序員會為了節省內存開支而犧牲程序的某些性能。但盡管WinCE系統的內存很小,用來管理內存的函數卻十分完善。Windows CE實現了Windows XP中幾乎全部的Win32內存管理API。例如,Windows CE支持虛擬內存分配,本地和分離的堆管理,甚至還有內存映射文件。像Windows XP一樣,Windows CE支持帶有應用程序間內存保護功能的32位地址空間,這一點對于多程序和多線程運行時是非常重要的功能。但是Windows CE畢竟是被設計來應用于實時場合的,所以它底層的內存結構又不同于Windows XP。
Windows CE內核可以在Flash上直接運行,也可以加載到內存中運行。Flash的運行方式,是把內核的可執行映像燒寫到Flash上,系統啟動時從Flash的某個地址開始執行。在這種情況下,Windows CE系統就像直接讀硬盤,存儲在Flash上的程序能夠以現場執行的方式運行。這種能力對小型系統來說使之在具有巨大的優勢,這樣這能快速啟動一個應用程序,因此這種方法被很多嵌入式系統所采用。另一種是內核加載方式,是把內核的壓縮文件存放在Flash上,系統啟動時讀取壓縮文件在內存里解壓,然后開始執行。
(2)虛擬內存和函數應用
和大多數現代操作系統一樣,Windows CE實現按需調頁的虛擬內存機制。由于Windows CE系統使用了虛擬內存,這就給應用程序造成了一個假象,以為計算機安裝的內存遠遠超過自己所需要的數量。Windows CE是32位的操作系統,因此支持4GB的虛擬地址空間。Windows把這些地址空間分給進程和系統使用,每個部分可以獲得2GB的虛擬內存。
虛擬內存是內存類型中基礎的。Windows CE 實現了系統的虛擬內存管理,在一個虛擬內存系統中,應用程序主要處理這個虛擬的地址空間,并不涉及到由硬件管理的物理內存。系統調用虛擬內存API來為其它類型內存分配內存,包括堆和棧。Windows CE虛擬內存頁可以處在三種狀態:自由(free),保留(reserved),或被提交(committed)。
簡單說,就是當一個應用程序要查詢系統的內存時,可使用虛擬內存API,包括VirtualAlloc,VirtualFree和VirtualReSize函數,這些函數可以直接操作虛擬內存空間的虛擬內存頁面。例如,頁面可以保留,提交給物理內存,或使用這些函數釋放。Windows CE實現了Win32的GetSystemInfo和GlobalMemoryStatus函數。另一個檢測系統狀態的函數是:void GlobalMemoryStatus(LPMEMORYSTATUS lpmst),通過GlobalMemoryStatus返回的信息可以驗證Windows CE內存結構。
(3)釋放虛擬內存
不同于Windows XP,Windows CE只支持在堆中分配固定(fixed)的塊。這簡化了內存塊在堆中的處理,但是這使得堆在分配和釋放一段時間后會產生碎片。當堆里已經清空的時候,仍然會占用大量的虛擬內存頁,因為系統不能在堆中內存頁沒有完全釋放的時候回收這些頁。這時,一般情況下是可以通過調用VirtualFree來取消提交,或釋放虛擬內存。從物理RAM頁中取消提交或者取消映射,但是保持頁被保留的狀態,當在區域中的所有的頁通過VirtualFree被釋放時,也應該處在同樣的情況下。更確切地說,區域中的全部頁要被釋放,那這些頁要么都是被提交的頁,要么都是被保留的頁。如果有些頁被提交,有些頁被保留,那么VirtualFree函數調用就會失敗。
實際上,Windows CE會監視系統自由的內存,并對越來越少的內存作出響應。當很少內存可用時,Windows CE首先發送WM_HIBERNATE消息,接下來會限制可能的內存分配。當應用程序被發送了一個WM_HIBERNATE消息后,系統將檢測內存級別,確認是否可用內存在限度之上,如果可用內存不足,WM_HIBERNATE消息將被發送給下一個程序,這會持續到所有程序被發送了WM_HIBERNATE消息。
讓我生不如死的Windows CE內存泄漏
更新時間: 2008-08-06 13:15:31來源: 粵嵌教育瀏覽量:1477