linux linux程序記憶體分析

2021-07-05 17:11:34 字數 3078 閱讀 1823

在產品的開發中,通過對當前系統消耗記憶體總量的統計,可以對產品所需記憶體總量進行精確的評估,從而選擇合適的記憶體晶元與大小,降低產品的成本。在遇到記憶體洩露類問題時,經常會對此束手無策,本文通過對proc下程序相關的檔案進行分析,精確評估系統消耗記憶體的大小,還可以對記憶體洩露類問題的解決提供一種定位手段。

linux在記憶體使用上的原則是:如果記憶體充足,不用白不用,盡量使用記憶體來快取一些檔案,從而加快程序的執行速度,而當記憶體不足時,會通過相應的記憶體**策略收回cache記憶體,供程序使用。

一、系統總記憶體的分析。

可以從proc目錄下的meminfo檔案了解到當前系統記憶體的使用情況彙總,其中可用的物理記憶體=memfree+buffers+cached,當memfree不夠時,核心會通過回寫機制(pdflush執行緒)把cached和buffered記憶體回寫到後備儲存器,從而釋放相關記憶體供程序使用,或者通過手動方式顯式釋放cache記憶體

echo 3 > /proc/sys/vm/drop_caches

二、程序使用記憶體的統計

在32位作業系統中,每個程序擁有4g的虛擬記憶體空間,其中0~3gb是每個程序的私有使用者空間,這個空間對系統中其他程序是不可見的。3~4gb是linux核心空間,由系統所有的程序以及核心所共享的。通過訪問/proc//下相關檔案,可以了解每個執行緒虛擬記憶體空間的使用情況,從而了解每個執行緒所消耗記憶體的多少。

由於我們的產品都是使用多執行緒方式實現的,多個執行緒共享乙個程序的使用者態虛擬位址空間,虛擬位址空間包含若干區域,主要有如下幾個區域:

1、當前執行檔案的**段,該**段稱為text段。

2、執行檔案的資料段,主要儲存執行檔案用到的全域性變數,靜態變數。

3、儲存全域性變數和動態產生的資料的堆。

4、用於儲存區域性變數和實現函式呼叫的棧。

5、採用mmap方式對映到虛擬位址空間中的記憶體段

所以只需要檢視任意乙個執行緒的使用者態虛擬位址空間分配即可知道屬於同一程序的所有執行緒占用總記憶體的大小。可以通過檢視/proc//maps檔案來獲取相關的虛擬位址空間內容,下文摘列部分典型的內容:

00008000-0036a000 r-xp 00000000 00:0e 236 /home/hik/hicore

00372000-003a5000 rw-p 00362000 00:0e 236 /home/hik/hicore

003a5000-00e28000 rwxp 003a5000 00:00 0 [heap]

40000000-40005000 r-xp 00000000 01:00 94 /lib/ld-uclibc.so.0

416db000-41770000 rw-s c2005000 00:0f 68 /dev/mem

b51fc000-b5200000 rwxp b51fc000 00:00 0

…….

be1fc000-be200000 rwxp be1fc000 00:00 0

be93b000-be950000 rwxp befeb000 00:00 0 [stack]

第一行:從r-xp可知其許可權為唯讀、可執行,該段記憶體位址對應於執行檔案的

**段,程式的**段需載入到記憶體中才可以執行。由於其唯讀,不會

被修改,所以在整個系統內共享。

第二行:從rw-p可知其許可權為可讀寫,不可執行,該段記憶體位址對應於執行檔案的資料段,存放執行檔案所用到的全域性變數、靜態變數。

第三行:從rwxp可知其許可權是可讀寫,可執行,位址空間向上增長,而且不對應檔案,是堆段,程序使用malloc申請的記憶體放在堆段。每個程序只有乙個堆段,不論是主程序,還是不同的執行緒申請的記憶體,都反映到到程序的堆段。堆段向上增長,最大可以增長到1gb的位置,即0x40000000,如果大於1gb,glibc將採用mmap的方式,為堆申請一塊記憶體。

第四行:是程式連線的共享庫的記憶體位址。

第五行:是以mmap方式對映的虛擬位址空間。

第六、七行:是執行緒的棧區位址段,每個執行緒的棧大小都是16k。

第八行:是程序的棧區。關於棧段,每個執行緒都有乙個,如果程序中有多個執行緒,則包含多個棧段。

三、當前系統總記憶體的統計

1、程序占用的總記憶體可以通過上述maps表計算出來。

2、當系統執行起來以後,會把應用層相關的檔案掛載到tmpfs檔案系統下,海思系統下這部分大概有13m左右,這部分記憶體是以cache方式統計出來的,但是這部分記憶體cache無法通過**策略或者顯式的呼叫釋放掉。

3、根檔案系統ramdisk占用的記憶體。

4、當前系統保留記憶體的大小,可以通過檢視/proc/sys/vm/min_free_kbytes來獲取或者修改此記憶體的大小。

5、當然,當系統執行起來後,還應該留有一定的記憶體用於在硬碟讀寫時做cache或者網路負荷比較高時分配skb等,一般需要30m以上。

四、對除錯記憶體洩露類問題的一些啟示

當程序申請記憶體時,實際上是glibc中內建的記憶體管理器接收了該請求,隨著程序申請記憶體的增加,記憶體管理器會通過系統呼叫陷入核心,從而為程序分配更多的記憶體。

針對堆段的管理,核心提供了兩個系統呼叫brk和mmap,brk用於更改堆頂位址,而mmap則為程序分配一塊虛擬位址空間。

當程序向glibc申請記憶體時,如果申請記憶體的數量大於乙個閥值的時候,glibc會採用mmap為程序分配一塊虛擬位址空間,而不是採用brk來擴充套件堆頂的指標。預設情況下,此閥值是128k,可以通過函式來修改此值。

#include

int mallopt(int param, int value)

param的取值分別為m_mmap_threshold、m_mmap_max。

value的取值是以位元組為單位的。

m_mmap_threshold是glibc中申請大塊記憶體閥值,大於該閥值的記憶體申請,記憶體管理器將使用mmap系統呼叫申請記憶體,如果小於該閥值的記憶體申請,記憶體管理器使用brk系統呼叫擴充套件堆頂指標。

m_mmap_max是該程序中最多使用mmap分配位址段的數量。

如果在實際的除錯過程中,懷疑某處發生了記憶體洩露,可以檢視該程序的maps表,看程序的堆段或者mmap段的虛擬位址空間是否持續增加,如果是,說明很可能發生了記憶體洩露,如果mmap段虛擬位址空間持續增加,還可以看到各個段的虛擬位址空間的大小,從而可以確定是申請了多大的記憶體,對除錯記憶體洩露類問題可以起到很好的定位作用。

Linux Linux程序間通訊之共享記憶體

1 共享記憶體概念引入 共享記憶體區是最快的ipc形式。一旦這樣的記憶體對映到共享它的程序的位址空間,這些程序間資料傳遞不再涉及到核心,換句話說是程序不再通過執行進入核心的系統呼叫來傳遞彼此的資料 2 共享記憶體資料結構 struct shmid ds struct ipc perm shm per...

linux linux程序指令

1.linux有哪些程序 linux下的主要程序狀態有 2.1 r task running 可執行狀態 通過將程序的task struct結構放到cpu的可執行佇列中,使程序變成r態。只有處在該狀態的程序才有可能被程序排程器選中在cpu上執行 2.2 s task interruptible 可中...

Linux linux程序間通訊

程序間通訊是指在不同程序之間傳播或交換資訊 程序間通訊可分為以下幾類 管道 匿名管道和命名管道 system ipc 訊息佇列 用於資料傳輸 共享記憶體 用於資料共享 訊號量 用於事件通知 posix ipc 訊息佇列 共享記憶體 互斥量條件變數 訊號量讀寫鎖 主要介紹常用的如管道 訊息佇列 訊號量...