1. 程式人生 > >嵌入式Linux記憶體使用與效能優化

嵌入式Linux記憶體使用與效能優化

1.  怎樣檢視系統當前可用記憶體 ?

答:使用 free 命令即可。如下圖所示:

說明:

buffers: 主要用來給Linux系統中塊裝置做緩衝區(把分散的寫操作集中進行,減少對磁碟或者Flash裝置的寫次數,提高系統性能)

cached:用來緩衝開啟的檔案(把從磁碟或者Flash中讀取的資料儲存在記憶體中,若再次讀取該塊時,則直接從記憶體中讀取而不需要再訪問磁碟或者Flash裝置)

在系統中記憶體是很寶貴的資源,故Linux在記憶體使用上的宗旨是:如果記憶體充足,不用白不用,儘量使用記憶體來快取一些檔案,從而加快程序的執行速度;而當記憶體不足的時候,這些記憶體又會被回收,供程式使用。

所以,當前系統真正空閒可以使用的記憶體為:free+buffers+cached (KB)

2.  free命令得到的資料是哪裡來的?

答: 來自 /proc 虛擬檔案系統,我們可以通過 /proc/meminfo檔案來了解當前系統的記憶體使用情況,如下圖所示:

從上面可以看出,系統一共有 2050600KB的實體記憶體,當前系統可用的實體記憶體為: Memfree+Buffers+Cached

3.  作業系統的虛擬記憶體與實體記憶體機制

作業系統為程式設計師遮蔽了實體記憶體的使用,在32位作業系統中,每個程序面對的都是4GB的記憶體空間,稱為虛擬記憶體。作業系統採用了延遲分配實體記憶體的策略,針對程序的記憶體分配請求,它只是在核心中分配了一段虛擬地址,只有當確實使用這塊記憶體時,系統才會為其分配實體地址。

我們來看一下下面這段程式碼: 

#include <stdio.h> #include <stdlib.h> #include <string.h>  int main() {     char * p = (char *)malloc(10);      char * q = (char *)malloc(200);      strcpy(p,"123");      return 0;  }

問題一:該程式碼執行時,記憶體的分配過程是怎樣的?

(1)  char * p= (char *)malloc(10);

   char *q =  (char *)malloc(200);

這2句,系統只給該程序分配了虛擬記憶體,而並沒有分配實體記憶體。

(2)  strcpy(p,"123");

這一句,由於程序需要真正使用這塊記憶體了,因此係統會產生一個頁故障,從而為該程序分配一個物理頁面。

(3)  整個程式最終只是為 p 分配的實體記憶體,而只是給 q 分配了虛擬記憶體。

問題二: 該程式碼實際分配的記憶體究竟多大?

系統給該程序分配的虛擬記憶體為 : 10B + 200B = 210 Byte

給該程序分配的實體記憶體為 4KB,因為系統規定,分配實體記憶體的最小單位為一個物理頁面,一般是4KB

注:使用者態申請記憶體是以Byte為單位,而核心態申請記憶體是以頁面(4KB)為單位

4.  Linux的記憶體回收機制

在Linux系統中,有一個專門的守護程序 kswapd,它會定期地檢查系統中空閒記憶體的數量,一旦發現空閒記憶體數量小於一個閾值的時候,就會將若干頁面換出,存放到交換分割槽中,以騰出足夠的記憶體空間。

對於交換分割槽的使用,有著如下的規則:

對於那些沒有被改寫過的頁面,這塊記憶體不需要寫到交換分割槽上,可以直接回收。

對於那些已經改寫的頁面,我們稱之為髒頁面(dirty page),則需要寫到交換分割槽。

但在使用Flash作為儲存介質的嵌入式裝置中,一般沒有交換分割槽,因此對於dirty page,只能保留在系統中,無法換出。原因如下:

(1) 一旦使用了交換分割槽,系統的效能會下降很快,不可接受

(2) Flash的寫次數是有限的,大概在幾十萬次,如果在Flash上面建立交換分割槽的話,必然導致對Flash的頻繁讀寫,進而影響Flash的壽命。

下面分析下,一個程序中,哪些記憶體可能是 dirty page 頁面,哪些不是?

(1) 程式碼段,其許可權是隻讀屬性,不可能被改寫,所以其所佔的實體記憶體,都不是 dirty page

(2) 資料段,其許可權是可讀、可寫,所以其所佔的實體記憶體可能是 dirty page,也可能不是

(3) 堆疊段,其沒有對應的對映檔案,內容都是通過程式來改寫的,所以其所佔的實體記憶體全部是 dirty page

(4) 共享記憶體,其所佔的實體記憶體,全部是 dirty page

綜上所述,也就是說, 可以直接被回收的記憶體,主要是程序的程式碼段和未修改的資料段。

5.  為什麼在 malloc時,要求輸入申請的空間大小,而在 free 時,不需要輸入釋放的空間大小?

    因為程式呼叫 malloc 函式申請記憶體時,並不是直接向作業系統申請,而是先由 glibc 的記憶體管器模組接收請求,它再通過系統呼叫向核心申請一塊記憶體並將地址p返回給使用者,同時,在 p-4 這個地址記錄下 malloc 空間的大小,glibc 在 free 這塊記憶體的時候,通過 p-4 即可知道需要釋放的記憶體大小是多少。