[心得] 要求系統釋放記憶體 |
|
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
「要求系統釋放記憶體」的心得
原理是在程式中動態配置一個很大的記憶體,比現有可用的實體記憶體還大,這時系統為了滿足這個「正在執行中」的程式的要求,於是將一些已不太使用的記憶體區塊放到虛擬記憶體中。 在實際撰寫「要求系統釋放記憶體」的程式時發現,當程式向系統要一塊很大的 Buffer 時,如 char *pBuffer=new char[200*1024*1024]; 系統並不是將「實體記憶體」分配給它,而是將「虛擬記憶體」分配給它。
當程式對於 pBuffer[i] 作存取時,才發現「實體記憶體」的大小開始變小了,不過此程式所占用的「虛擬記憶體」並沒有變小喔。而當「實體記憶體」變得只剩不到 1MB 時,可以發現系統速度變慢了,這是因為系統開始整理記憶體了,把一些已不太使用的記憶體區塊釋放,此時,可以發現其他程式所占用實體記憶體的大小開始變小了,同樣地,其他程式所占用的「虛擬記憶體」並沒有變小或變大,也就是說,沒有所謂「將不用的實體記憶體放到虛擬記憶體」?是這樣嗎? 但是程式執行速度明顯變慢,而且可以看到(聽到)硬碟正在努力地存取中,有可能是將不用的實體記憶體內的資料「更新」回虛擬記憶體中。(這只是猜想) 為了加快此程式釋放記憶體的速度,於是筆者將存取 pBuffer[i] 由每 byte 都存取,改成每 1KB 只存取 1 byte、再改成每 2KB 只存取 1 byte、再改成每 4KB 只存取 1 byte、再改成每 8KB 只存取 1 byte...
當改成每 8KB 只存取 1 byte 在釋放記憶體時,發現此程式所占用的實體記憶體並沒有每 4KB 只存取 1 byte 時來得大,這也使得釋放記憶體功能失效!所以,最佳的狀態是每 4KB 只存取 1 byte,而這也有可能因系統而異。 【結論】
在釋放記憶體的過程中,其他程式所占用的虛擬記憶體並沒有增大!可以大膽的推論,程式所有必要的程式資料碼都已放在虛擬記憶體中,而在執行的過程,才將有用到的部分移到實體記憶體中執行。 而系統在使用實體記憶體時,是以 Page 為單位,一個程式在執行時有用到的程式或資料會放到可用的 Page 中,而程式所「認知」的記憶體位址,其實是系統「告知」的,所以有可能在程式中認為一個 Buffer 在執行時其記憶體是「連續」的,但這是經由系統適當配置後,讓這個程式認為它所用的 Buffer 記憶體是連續的,但真正所使用到的實體記憶體很有可能是四分五裂的區塊!
在筆者的系統中,一個 Page 的大小也許就是 4KB,這可以解釋當存取間隔是在 4KB 以下時,其占用實體記憶體的狀況相近,而當存取間隔大於 4KB 如 8KB 時,雖然在程式中也是「連續」地使用它,但它真正在實體記憶體中卻只有 8KB 中有存取到的那一個 byte 被放到一個 4KB 的 Page 中。
void __fastcall TFormMemFree::FreeMemory(int iFreeSize) { this->Caption="記憶體釋放中..."; iFreeSize=iFreeSize << 20; // 單位為 MB // 方法1:無效 // char *pBuffer=new char[iFreeSize]; // delete [] pBuffer; // 方法2:有效,要真的去存取資料才會真的配置?! char *pBuffer=new char[iFreeSize]; int iStep=4*1024; // 實驗結果 1K,2K,4K 可,8K 以上太大就不行 for(int i=iStep-1;i<iFreeSize;i = iStep) // 以 K 為單位,加快存取時間 { if(bAbort) break; // 如果要求中止,則不再向系統要記憶體 pBuffer[i]=0x0; iFreeingPercent=((i 1)>>10)*100/(iFreeSize>>10); this->Caption="記憶體釋放中..." IntToStr(iFreeingPercent) " %"; Application->ProcessMessages(); } delete [] pBuffer; this->Caption="記憶體釋完成!!"; }以上的推論都是按實測的結果及小弟個人的推理所得,小弟必需先聲明,我沒有上過、看過任何作業系統的書及課,所以,以上的推論可能有錯,請懂原理的網友多多指教,讓小弟可以更了解記憶體管理。
------
http://www.ViewMove.com |
ddy
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:262 回覆:2105 積分:1169 註冊:2002-07-13 發送簡訊給我 |
dllee兄果然夠精實…呵呵:p
以我的了解(與轉錄候捷的大作) 目前的電腦不可能安插 4GB 記憶體,所以作業系統使用一個磁碟置換檔
(disk swap file)暫時接受實際記憶體無法容納的資料。
因此雖然電腦只有 128MB 或 256MB,應用程式卻可能取用 4GB 虛擬記憶體。
不過,作業系統必須能夠把 page(虛擬記憶體的運作單位)搬移到實際記憶體的任何一個地點才行。(符合dllee兄的論點)
虛擬位址對應用程式而言是不變的;將它轉換為實際位址,是CPU 的責任 。 但是程式執行速度明顯變慢,而且可以看到(聽到)硬碟正在努力地存取中,有可能是將不用的實體記憶體內的資料「更新」回虛擬記憶體中。(這只是猜想)
==我覺得是將不常用的頁面(RAM中)與Virtual memory 的頁面交換 == ---以下結錄候捷的windows 95 programming---
---所以推論"虛擬記憶體之所以沒有變小,可能是僅有狀態的改變" 分頁機制使得作業系統得以保留巨大的記憶體位址範圍,直到真正需要 RAM 為止。 任何時候,CPU 的 4GB 位址空間中,每一個 4K 區段(一頁)有四種可能的狀態:
狀態1:Available ,表示這頁記憶體並沒有保留給任何人。任何人可以經由配
置動作擁有它。企圖讀寫這塊記憶體將會導至 "page fault" 異常情況(exception
0Eh ) 狀態2:Reserved ,表示這一頁已經被某人要走了。然而,RAM 還沒有被映
射到這個位址,也沒有任何硬碟空間保留用來複製其內容。企圖讀寫這塊記憶
體將會導至 "page fault" 異常情況(exception 0Eh )。作業系統給予這個區塊
的擁有者一個機會,把狀態改變為 Committed and Present 。 狀態3:Committed and present ,表示這位址已經被配置給某人,並且有一
個程式已經用它來儲存資料。CPU 的分頁機制也已經把 4K RAM 映射到此
位址。讀寫此塊位址也就是讀寫映射之實際記憶體。這個狀態還有一個子狀態
稱為 pagelocked ,表示這一頁是 committed 、present 、並保證絕不會被置換
(swapped out )出去。當 page 處於 pagelocked 狀態,永遠會有實際記憶體
映射到該 page ,直到它變成 unpagelocked 狀態。 狀態4:Committed and not-present ,這和前一狀態十分類似,程式已經配置
此塊記憶體並用它來儲存資料。不同之處在於作業系統已經決定,其他地方更迫
切需要映射至此區的RAM 。因此,CPU 已經把此區內容拷貝到硬碟之中,
並把此區的每一頁標記為 Not Present (譯註:Not Present 表示位址並沒有映
射到實際記憶體)。
和狀態1 、狀態2 一樣,如果這樣的 page 被存取,會發生 page fault 。
不同之處在於當程式存取這樣的位址,作業系統會自動處理page fault 異常情況並重新映射一塊
4MB RAM 過來。然後作業系統會讀取硬碟中的原來資料,再重新執行發生 page fault
之前的那個指令。於是程式完全不知道有 page fault 發生。這樣透明化的以硬碟模擬
RAM 正是虛擬記憶體的基礎。 噓~~~~~~沉思中…
|
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
|
ddy
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:262 回覆:2105 積分:1169 註冊:2002-07-13 發送簡訊給我 |
嗚~~~~~~剛剛打的都不見了><~~~ dllee兄
以我所知,頁面大小是可以改變的
但是頁面管理是CPU與作業系統的配合
除非是要RUN不同的硬體平台,不然單單改作業系統,也不見得能正常運作
就像X86 CPU一個Page就是4k
Alpha CPU一個Page就是8k
在Linux裡的Source code 有Page size 的變數可改,應是為了不同平台的相容吧,Windows 95/98 系列應該就是4k,NT系統就不一定吧,因為NT好像也能跑Alpha 的CPU吧…(:p~~不太確定)
Red hat Linux 7.3裡的/usr/src/linux-2.4.18-3/mm 裡有Linux記憶體管理的Source code ,我大致看過了…嗯…太深奧了^^|||
您有興趣可以安裝玩玩看,了解一下 您執行完PSP後,所佔的memory,並不是被釋放
此時它的狀態應該是由Committed and present狀態的子狀態pagelocked 改變為unpagelocked (並非主動釋出頁面對應)
然後unpagelocked狀態回復至Reserved,表示這一頁目前仍被某程式佔用。然而,RAM 目前還沒有新的內容映射到這個位址,也沒有任何硬碟空間保留用來複製其內容。若其它程式企圖讀寫這塊記憶體將會導至 "page fault" 異常情況(exception 0Eh )。作業系統給予這個區塊
的擁有者一個機會,把狀態改變為 Committed and Present 或是Committed and not-Present
不斷的發生page fault(尋頁缺失)不斷的改變狀態,直至停止發生page fault 以上是我的看法啦…:p 呵呵…愈來愈心虛了
如果觀念有誤,請高手指教 噓~~~~~~沉思中…
|
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
引言: 嗚~~~~~~剛剛打的都不見了><~~~哇!您也遇到了!有時真的是很想哭吧
------
http://www.ViewMove.com |
ddy
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:262 回覆:2105 積分:1169 註冊:2002-07-13 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |