1.程序的VMA
(1)程序位址空間
在Linux系統中,每個程序都有自己的虛拟記憶體空間0~3G;
核心空間隻有一個3G~4G;

程序通過系統API調用,在核心空間申請記憶體,不統計在任何使用者程序;程序消耗記憶體,單指使用者空間記憶體消耗;
(2)VMA清單
LINUX用task_struct來描述程序,其中的mm_struct是描述記憶體的結構體,mm_struct有一個vma清單,管理目前程序的所有vma段。
每個程序的記憶體由多個vma段組成:
(3)檢視VMA方法:
1.pmap
由圖知,從接近0位址開始,第一個4K是隻讀代碼段,第二個4K是隻讀資料段,還有其他共享庫代碼段,堆棧等;
可見一個程序的VMA涵蓋多個位址區域**,但并沒有覆寫所有位址空間**。VMA未覆寫的位址空間是illegal的,通路這些位址,缺頁中斷,發生pagefault.
2.cat /proc/pid/maps
讀檔案形式,與pmap一一對應;
3.cat /proc/pid/smaps
更詳細的描述
00400000-00401000 r-xp 00000000 08:15 20316320 /home/leon/work/linux/mm/a.out
Size: 4 kb
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 4 kB
Private_Dirty: 0 kB
Referenced: 4 kB
Anonymous: 0 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
VmFlags: rd ex mr mw me dw sd
檢視VMA的三個方法對比
VMA的來源,代碼段,資料段,堆棧段。
VMA是linux最核心資料結構之一。
2.page fault的幾種可能性,major和minor
mmu給cpu發page fault時,可以從寄存器讀到兩個元素,pagefault位址,pagefault原因。
(1)通路Heap堆(首次申請,不是從Libc擷取),第一次寫,發生pagefault,linux檢查VMA權限,發現權限合法,發缺頁中斷,申請一頁記憶體,并更新頁表。
(2)通路空區域,通路非法,發段錯誤;
(3)通路代碼段, 在此區域寫,報pagefault,檢查權限發現錯誤,報段錯誤;
(4)通路代碼段,在此區域讀/執行,linux檢查權限合法,若代碼不在記憶體,那麼申請記憶體頁,把代碼從硬碟讀到記憶體。
伴随I/O的pagefault, 叫major pagefault, 否則minor pagefault.
major pagefault耗時遠大于 minor pagefault.
\time -v python hello.py
3.記憶體是如何被瓜分的: :vss、rss、pss和uss
rss是不是代表程序的記憶體消耗呢,NO。
VSS:單個程序全部可通路的位址空間,但未必所有虛拟位址都已經映射實體記憶體;
RSS:駐留記憶體,單個程序實際占用的實體記憶體大小(不十分準确的描述);上圖的程序1
PSS:
比例化的記憶體消耗,相對RSS,将共享記憶體空間按被共享程序數量比例化;上圖的C庫4被三個程序共享,是以4/3;
USS:程序獨占記憶體,比如上圖的堆6。
案例,連續運作兩次a.out,檢視記憶體占用情況
運作程式a.out
./a.out &
pidof a.out
cat /proc/pid/smaps |more
&
cat /proc/pid_2/smaps |more
PSS變化
shared_clean
private_clean
4.應用記憶體洩漏的界定方法
統計系統的記憶體消耗,檢視PSS。
檢查有沒有記憶體洩漏,檢查USS
./smem
smem –pie=command
smem –bar=command
android裡面有類似的工具,procmem/procrank
smem分析系統記憶體使用是通過/proc/smaps的,procrank是通過分析/proc/kpagemap。
5.應用記憶體洩漏的檢測方法:valgrind和addresssanitizer
其他查詢記憶體洩漏工具:
valgrind:
gcc -g leak-example.c -o leak-example
valgrind --tool=memcheck --leak-check=yes ./leak-example
20468 HEAP SUMMARY:
20468 in use at exit: 270,336 bytes in 22 blocks
20468 total heap usage: 44 allocs, 22 frees, 292,864 bytes allocated
20468
20468 258,048 bytes in 21 blocks are definitely lost in loss record 2 of 2
20468 at 0x4C2DB8F: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
20468 by 0x4005C7: main (leak-example.c:6)
valgrid是在虛拟機跑APP,速度很慢;
新版gcc4.9以後內建了asan
asan:
gcc -g -fsanitize=address ./leak-example.c
gcc -fuse-ld=gold -fsanitize=address -g ./lsan.c
#1 0x40084e in main lsan.c:9
記憶體洩漏不一定在使用者空間,排查核心空間,檢測slab , vmalloc
slaptop, 檢查申請和釋放不成對。
在核心編譯,打開kmemleak選項。
5.工程調試記憶體洩漏問題一般步驟:
(1) meminfo, free 多點采樣确認有記憶體洩漏。
(2)定位,smem檢查使用者空間
USS在不斷增加。
cat
cat /proc/meminfo
cat /proc/buddyinfo
cat /proc/zoneinfo
cat