郝健: Linux内存管理学习笔记-第3节课
摘要
進(jìn)程的虛擬地址空間VMA(Virtual Memory Area)
Pagefault的幾種可能性、VMA的作用、major缺頁和minor缺頁
進(jìn)程內(nèi)存消耗的4個(gè)概念:vss、rss、pss和uss
應(yīng)用內(nèi)存泄漏的界定方法
內(nèi)存泄漏的檢測工具:valgrind和addresssanitizer
?
?
1.????進(jìn)程的虛擬地址空間VMA(Virtual Memory Area)
上圖中,task_struct中的mm_struct就代表進(jìn)程的整個(gè)內(nèi)存資源,mm_struct中的pgd為頁表,mmap指針指向的vm_area_struct鏈表的每一個(gè)節(jié)點(diǎn)就代表進(jìn)程的一個(gè)虛擬地址空間,即一個(gè)VMA。一個(gè)VMA最終可能對應(yīng)ELF可執(zhí)行程序的數(shù)據(jù)段、代碼段、堆、棧、或者動(dòng)態(tài)鏈接庫的某個(gè)部分。
?
VMA的分布情況可以有通過pmap命令,及maps,smaps文件查看,如下圖:
pmap pid
pmap - report memory map of a process
?
/proc/<pid>/maps及/proc/<pid>/smaps更詳細(xì)展示了進(jìn)程VMA的分布情況。
?
觀察pmap結(jié)果及maps,smaps文件,可以發(fā)現(xiàn)注:IA32下,一個(gè)進(jìn)程的VMA是在0~3G之間分散分布的,是一段一段的,中間會(huì)有很多空白區(qū)域,空白區(qū)域?qū)M(jìn)程來說都是不能訪問的,VMA中會(huì)標(biāo)注這一段的RWX的具體權(quán)限。如下圖所示:
另,VMA的具體內(nèi)容可參考下圖。
2.????Page fault的幾種可能性、VMA的作用、major缺頁和minor缺頁
1)如,調(diào)用malloc申請100M內(nèi)存,IA32下在0~3G虛擬地址中立刻就會(huì)占用到大小為100M的VMA,且符合堆的定義,這一段VMA的權(quán)限是R+W的。但由于Lazy機(jī)制,這100M其實(shí)并沒有獲得,這100M全部映射到一個(gè)物理地址相同的零頁,且在頁表中記錄的權(quán)限為只讀的。當(dāng)100M中任何一頁發(fā)生寫操作時(shí),MMU會(huì)給CPU發(fā)page fault(MMU可以從寄存器讀出發(fā)生page fault的地址;MMU可以讀出發(fā)生page fault的原因),Linux內(nèi)核收到缺頁中斷,在缺頁中斷的處理程序中讀出虛擬地址和原因,去VMA中查,發(fā)現(xiàn)是用戶程序在寫malloc的合法區(qū)域且有寫權(quán)限,Linux內(nèi)核就真正的申請內(nèi)存,頁表中對應(yīng)一頁的權(quán)限也修改為R+W。
2)如,程序中有野指針飛到了此程序運(yùn)行時(shí)進(jìn)程的VMA以外的非法區(qū)域,硬件就會(huì)收到page fault,進(jìn)程會(huì)收到SIGSEGV信號報(bào)段錯(cuò)誤并終止。
3)如,代碼段在VMA中權(quán)限為R+X,如果程序中有野指針飛到此區(qū)域去寫,則也會(huì)發(fā)生段錯(cuò)誤。(另,malloc堆區(qū)在VMA中權(quán)限為R+W,如果程序的PC指針飛到此區(qū)域去執(zhí)行,同樣發(fā)生段錯(cuò)誤。)
4)如,執(zhí)行代碼段時(shí)會(huì)發(fā)生缺頁,Linux申請1頁內(nèi)存,并從硬盤讀取出代碼段,此時(shí)產(chǎn)生了IO操作,為major主缺頁。
綜上,page fault后,Linux會(huì)查VMA,也會(huì)比對VMA中和頁表中的權(quán)限,體現(xiàn)出VMA的重要作用。
?
3.????進(jìn)程內(nèi)存消耗的4個(gè)概念:vss、rss、pss和uss
首先,我們評估一個(gè)進(jìn)程的內(nèi)存消耗都是指用戶空間的內(nèi)存,不包括內(nèi)核空間的內(nèi)存消耗,即IA32下,虛擬地址在0~3G的部分所對應(yīng)的物理地址的內(nèi)存。
VSS - Virtual Set Size
RSS - Resident Set Size
PSS - Proportional Set Size
USS - Unique Set Size
1044,1045,1054三個(gè)進(jìn)程,每個(gè)進(jìn)程都有一個(gè)頁表,對應(yīng)其虛擬地址如何向real memory上去轉(zhuǎn)換。
process 1044的1,2,3都在虛擬地址空間,所以其VSS=1+2+3。
process 1044的4,5,6都在real memory上,所以其RSS=4+5+6。
?
分析real memory的具體瓜分情況:
4 ?libc代碼段,1044,1045,1054三個(gè)進(jìn)程都使用了libc的代碼段,被三個(gè)進(jìn)程分享。
5 ?bash shell的代碼段,1044,1045都是bash shell,被兩個(gè)進(jìn)程分享。
6 ?1044獨(dú)占
所以,上圖中4+5+6并不全是1044進(jìn)程消耗的內(nèi)存,因?yàn)?明顯被3個(gè)進(jìn)程指向,5明顯被2個(gè)進(jìn)程指向,衍生出了PSS(按比例計(jì)算的駐留內(nèi)存)的概念。進(jìn)程1044的PSS為4/3 +5/2 +6。
最后,進(jìn)程1044獨(dú)占且駐留的內(nèi)存USS為 6。
?
一般情況下,VSS >= RSS >= PSS >= USS。
?
評估進(jìn)程內(nèi)存耗費(fèi)情況一般使用smem工具,查看PSS(最公平):
1)命令行模式
2)餅狀圖模式
3)柱狀圖模式
跑一個(gè)死循環(huán)程序,觀察其smaps文件。然后再把此程序跑一份,觀察其smaps文件變化(smaps內(nèi)容很長,只看第一段):
可以看出PSS由4k變?yōu)?k,而Shared_clean由0k變?yōu)?k,Private_clean由4k變?yōu)?k。
?
4.????應(yīng)用內(nèi)存泄漏的界定方法
內(nèi)存泄漏:進(jìn)程運(yùn)行的時(shí)間越久,耗費(fèi)的內(nèi)存越多,申請與釋放不成對。
內(nèi)存泄漏只看USS即可。
觀察內(nèi)存泄漏使用連續(xù)多點(diǎn)采樣法:
?
5.????內(nèi)存泄漏的檢測工具:valgrind和addresssanitizer
每次free(p2),沒有free(p1),申請與釋放不成對。
?
使用valgrind檢測由內(nèi)存泄漏的程序:
使用addresssanitizer中的lsan工具檢測程序內(nèi)存泄漏:
調(diào)用 __lsan_do_leak_check()做檢查
檢測出泄漏了10次。
如今更流行使用addresssanitizer。
內(nèi)存管理報(bào)名
報(bào)名:《Linux的任督二脈》之《內(nèi)存管理》微課(連續(xù)5晚)
總結(jié)
以上是生活随笔為你收集整理的郝健: Linux内存管理学习笔记-第3节课的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Visual Studio 2013 e
- 下一篇: ImportError: No modu