1. 程式人生 > >程式佔用的記憶體分析

程式佔用的記憶體分析

轉載地址:http://blog.csdn.net/luansxx/article/details/7702030

作業系統的虛擬記憶體分配表


OP顯示的佔用記憶體是程序的虛擬記憶體,我們需要了解的是程式實際佔用記憶體的量,也就是實體記憶體佔用。

虛擬記憶體的地址和實際實體記憶體的地址之間有對應關係,這個關係是作業系統維護的,CPU負責根據這個對應關係進行地址轉換。這種對應關係標準的說法叫“記憶體對映”。

記憶體對映以頁面對映形式實現。頁面是固定大小的地址空間(即虛擬範圍),虛擬記憶體的一個頁面對映到實體記憶體的一個頁面。沒有必要假設連續的虛擬頁面對映到連續的物理頁面,即使物理頁面不連續,只要虛擬頁面連續,必要記憶體的一段地地址擬地己的虛擬地址空間(即虛擬地址範圍),因為程式看到的就是連續的資料,這中間就是地址轉換在起作用。

記憶體對映是一種複雜的關係,有下面的情形。

1.         虛擬頁面沒有對映物理頁面

2.         虛擬頁面對映某個物理頁面

3.         多個虛擬頁面對映同一個物理頁面

當然不可能一個虛擬頁面對映到多個物理頁面。

虛擬記憶體是程序自身的,每個程序有自己的虛擬地址空間(即虛擬地址範圍),虛擬地址空間獨立,也就是每個程序都是獨立的4G地址空間,但是實際實體記憶體很難有這麼多(特別是嵌入式平臺),所以虛擬地址空間可以看成是肯定足夠的。

因為虛擬地址空間很大,所以寧可浪費虛擬地址空間也要節約實體記憶體。對於一個程序來說,虛擬記憶體使用量與實體記憶體使用量的差別源於上面的第1、3種對映情形。第2種情形兩者是一對一對映,所以數量上一樣。

我們再看看第1、3種對映情形的實際應用。

對於第1種情形,虛擬頁面沒有對映物理頁面,一般發生在下列場合:

1.         程式的部分程式碼,因為某些條件未滿足,目前還沒有執行。

作業系統採用延遲載入策略,沒有訪問到的虛擬地址預設沒有對映到實體記憶體,是無效的;但是一旦被執行,就會分配一個物理頁面,從程式檔案中載入資料(程式碼也是二進位制資料)到該物理頁面,並修改對映關係,使虛擬地址生效。另外如果某些程式碼比較長時間沒有被執行(作業系統記錄頁面的空閒時間),作業系統會解除對映,釋放實體記憶體,因為記憶體上的資料以後還可以再載入。

2.         程式的靜態資料,因為某些條件未滿足,還沒有被訪問到

程式的靜態資料也是在程式檔案中的,包括全域性變數、字串和編譯器產生的靜態表。與上面的原理一樣,作業系統採用延遲載入策略和回收策略(只針對沒有修改過的記憶體,除非有交換分割槽,這時可以儲存在交換分割槽中)。

3.         堆中的空洞

程式的堆是程式動態申請釋放記憶體所用的記憶體池。堆可以向上增長,也會退回。但是必須靠後的記憶體都釋放了,而且堆的大小超過一定量(很多系統是128K)才退回。如果程式釋放了前面或者中間的記憶體,那是不會退回的,這就形成了空洞。空洞對映物的理記憶體實際上是已經釋放了,所以空洞沒有對映實體記憶體。

4.         棧頂保留地址空間

程式的棧是函式一層層呼叫形式的,函式一層層呼叫的返回地址記錄在棧中,函式呼叫的引數、函式內部的區域性變數都存放在棧中。隨著函式返回,區域性變數、引數等都被釋放,棧佔用的記憶體又回退回來。由於難以估計函式呼叫層次最大會有多深,所以棧會多保留一些虛擬地址空間,這些虛擬地址空間也採用延遲對映的策略和回收策略(退回的資料肯定沒有用了)。

5.         棧頂保護地址空間

如果程式有行為異常,對棧的使用超過了配置量,應該儘快發現,方法是在棧頂端後面額外加上小塊(一般一個頁面)虛擬地址空間,該地址沒有任何許可權(不能讀寫),一旦讀寫這塊記憶體,作業系統會直接給程序發訊號殺死程序。

對於第2種情形,多個虛擬頁面對映同一個物理頁面,一般發生在下列場合:

1.         多個程序共用同一份程式碼

這種情形一般發生的使用共享庫的時候,還有就是同一個程式啟動了多次。因為程式碼可以共用,所以同一份程式碼在實體記憶體中只會有一份,多個程序的虛擬地址都對映到同一個實體地址上。

2.         多個程序共用同一份資料

與上面的情形相同,但必須是隻讀的資料(其實程式碼就是隻讀資料)。

3.         程序內部通過不同許可權對映同一段實體記憶體

這種情形很容易被忽略。實體記憶體按頁面大小分配,如果資料量不是頁面大小的整數倍,那麼剩餘零頭對實體記憶體就形成了浪費。如果兩種訪問屬性的資料(比如程式碼有讀、執行情形,只讀資料只有讀許可權),他們的大小相當於頁面大小都有一部分零頭,那麼可以把這兩個零頭拼在一起放在一個物理頁面上,然後通過兩個虛擬頁面對映,就能夠到達節約記憶體的同時,仍能進行許可權控制力的目的。

綜上,程式實際佔用實體記憶體的計算方法應該是:

程式佔用記憶體  =  對映實體記憶體的加權和

加權值  =  本程式對該實體記憶體的對映次數  /  該實體記憶體在整個系統中被對映的次數

簡單的講,要從虛擬記憶體量中第1、3種對映情形多算的佔用量。第1種情形要全部減去,第3種情形要整個系統做一下平均,取平均值。

0
0