內(nèi)存消耗和泄漏
- 進(jìn)程的VMA
- 進(jìn)程內(nèi)存消耗的4個(gè)概念: vss、rss、pss和uss
- page fault的幾種可能性, major 和 minor
- 應(yīng)用內(nèi)存泄漏的解決方法
- 應(yīng)用內(nèi)存泄漏的檢測(cè)方法:valgrind 和 addresssanitizer
本節(jié)重點(diǎn)闡述 Linux的應(yīng)用程序究竟消耗了多少內(nèi)存?
一是,看到的內(nèi)存消耗,并不一定是真的消耗。
二是,Linux存在大量的內(nèi)存共享的情況。
動(dòng)態(tài)鏈接庫(kù)的特點(diǎn):代碼段共享內(nèi)存,數(shù)據(jù)段寫時(shí)拷貝。
把一個(gè)應(yīng)用程序跑兩個(gè)進(jìn)程,這兩個(gè)進(jìn)程的代碼段也是共享的。
當(dāng)我們?cè)u(píng)估進(jìn)程消耗多少內(nèi)存時(shí),就是指在用戶空間消耗的內(nèi)存,即虛擬地址在0~3G的部分,對(duì)應(yīng)的物理地址內(nèi)存。內(nèi)核空間的內(nèi)存消耗屬于內(nèi)核,系統(tǒng)調(diào)用申請(qǐng)了很多內(nèi)存,這些內(nèi)存是不屬于進(jìn)程消耗的。
進(jìn)程的虛擬地址空間VMA
task_struct里面有個(gè)mm_struct指針, 它代表進(jìn)程的內(nèi)存資源。pgd,代表 頁(yè)表的地址; mmap 指向vm_area_struct 鏈表。 vm_area_struct 的每一段代表進(jìn)程的一個(gè)虛擬地址空間。vma的每一段,都可能是可執(zhí)行程序的某個(gè)數(shù)據(jù)段、某個(gè)代碼段,堆、或棧。一個(gè)進(jìn)程的虛擬地址,是在0~3G之間任意分布的。
上圖 提供三種方式,看到進(jìn)程的VMA空間。pmap 3474其地址,size, 權(quán)限,通過以上的方式,可以看到進(jìn)程的虛擬地址空間,分布在0~3G,任意一小段一小段分布的。應(yīng)用程序運(yùn)行起來(lái),就是一堆各種各樣的VMA。VMA對(duì)應(yīng)著 堆、棧、代碼段、數(shù)據(jù)段、等,不在任何段里的虛擬地址空間,被認(rèn)為是非法的。
當(dāng)指針訪問地址時(shí),落在一個(gè)非法的地址,即不在任何一個(gè)VMA區(qū)域。相當(dāng)于訪問一個(gè)非法的地址,這些虛擬地址沒有對(duì)應(yīng)的物理地址。應(yīng)用程序收到page fault,查看原因,訪問非法位置,返回segv。
在VMA的東西,不等于在內(nèi)存。調(diào)malloc申請(qǐng)了100M內(nèi)存,立馬會(huì)多出一個(gè)100M的 VMA,代表這段vma區(qū)域有r+w權(quán)限。
應(yīng)用程序訪問內(nèi)存,必須落在一個(gè)VMA里。其次,落在一個(gè)VMA里也不一定對(duì)。把100M的堆申請(qǐng)出來(lái),100M內(nèi)存頁(yè)全部映射為0頁(yè)。頁(yè)表里每一頁(yè)寫的只讀,頁(yè)表和硬件對(duì)應(yīng),MMU只查頁(yè)表。而在頁(yè)表項(xiàng)中指向物理地址的權(quán)限是只讀,所以在任何時(shí)候,去寫其中任何一頁(yè),硬件都會(huì)發(fā)生缺頁(yè)中斷。
Linux 內(nèi)核在缺頁(yè)中斷的處理程序,通過MMU寄存器讀出發(fā)生page fault的地址和原因。發(fā)現(xiàn)此時(shí)page fault的原因是寫一個(gè)頁(yè)表里記錄只讀的物理地址,而vma記錄的虛擬地址又是r+w,此時(shí),linux會(huì)申請(qǐng)一頁(yè)內(nèi)存。同時(shí)把頁(yè)表中的權(quán)限改為r+w。
總結(jié):
Linux 內(nèi)核通過VMA管理進(jìn)程每一段虛擬地址空間和權(quán)限。一旦發(fā)生page fault,如果沒有落在任何一個(gè)vma區(qū)域,會(huì)干掉。VMA的起始地址+size,用來(lái)限定程序訪問的地址是否合法。VMA中每一段的權(quán)限,是來(lái)界定訪問這段地址是否使用正確的方式訪問。把所有的vma加起來(lái),構(gòu)成進(jìn)程的虛擬地址空間,但這并不代表進(jìn)程真實(shí)耗費(fèi)的內(nèi)存。拿到之后才是真實(shí)耗費(fèi)的內(nèi)存,RSS。耗費(fèi)的虛擬內(nèi)存,是VSS。
1、申請(qǐng)堆內(nèi)存vma,第一次寫,頁(yè)表里的權(quán)限是R ,發(fā)生page fault,linux會(huì)去申請(qǐng)一頁(yè)內(nèi)存,此時(shí)把頁(yè)表權(quán)限設(shè)置為 R+W。
2、內(nèi)存訪問落在空白非法區(qū)域,程序收到segv段錯(cuò)誤。
3、代碼段在VMA記錄是R+X,此時(shí)如果對(duì)代碼段執(zhí)行寫,程序會(huì)收到segv段錯(cuò)誤。
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【865977150】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦??!
內(nèi)核學(xué)習(xí)網(wǎng)站:
Linux內(nèi)核源碼/內(nèi)存調(diào)優(yōu)/文件系統(tǒng)/進(jìn)程管理/設(shè)備驅(qū)動(dòng)/網(wǎng)絡(luò)協(xié)議棧-學(xué)習(xí)視頻教程-騰訊課堂?ke.qq.com/course/4032547?flowToken=1040236
minor 和major 缺頁(yè)
缺頁(yè),分為兩種情況:主缺頁(yè) 和次缺頁(yè)。
主缺頁(yè) 和次缺頁(yè),區(qū)別就是 申請(qǐng)內(nèi)存時(shí),是否需要讀硬盤。前者需要。
如上圖第4種情況,在代碼段里執(zhí)行時(shí),出現(xiàn)缺頁(yè)。linux申請(qǐng)一頁(yè)內(nèi)存,而且要從硬盤中讀取代碼段的內(nèi)容,此時(shí)產(chǎn)生了IO,稱為 major缺頁(yè)。
無(wú)論是代碼段還是堆,都是邊執(zhí)行邊產(chǎn)生缺頁(yè)中斷,申請(qǐng)實(shí)際的內(nèi)存給代碼段,且從硬盤中讀取代碼段的內(nèi)容到內(nèi)存。這個(gè)過程時(shí)間比較長(zhǎng)。
minor: malloc的內(nèi)存,產(chǎn)生缺頁(yè)中斷。去申請(qǐng)一頁(yè)內(nèi)存,沒有產(chǎn)生IO的行為。major缺頁(yè)處理時(shí)間,遠(yuǎn)大于minor。
vss、rss、pss和uss的區(qū)別
VSS - Virtual Set Size
RSS - Resident Set Size
PSS - Proportional Set Size
USS - Unique Set Size
ASAN - AddressSanitizer
LSAN - LeakSanitizer
如上圖,中間是一根內(nèi)存條。三個(gè)進(jìn)程分別是1044,1045,1054, 每一個(gè)進(jìn)程對(duì)應(yīng)一個(gè)page table,頁(yè)表項(xiàng)記錄虛擬地址如何往物理地址轉(zhuǎn)換。硬件里的寄存器,記錄頁(yè)表的物理地址。當(dāng)linux做進(jìn)程上下文切換時(shí),頁(yè)表也跟著一起切換。
三個(gè)進(jìn)程都需要使用libc的代碼段:
VSS = 1 +2 +3
RSS = 4 +5 +6
PSS= 4/3 + 5/2 + 6 比例化的
USS= 6 獨(dú)占且駐留的
工具:smem ,查看進(jìn)程使用內(nèi)存的情況。
一般來(lái)講,進(jìn)程使用的內(nèi)存量,還是看PSS,強(qiáng)調(diào)公平性。看內(nèi)存泄漏看USS 就好了。
內(nèi)存泄漏 界定和檢測(cè)方法
界定:連續(xù)多點(diǎn)采樣法,隨著時(shí)間越久,進(jìn)程耗費(fèi)內(nèi)存越多。主要由內(nèi)存申請(qǐng)和釋放不是成對(duì)引起。RSS/USS曲線,觀察方法:使用smem工具查看多次進(jìn)程使用內(nèi)存,USS使用量。
檢查工具:
1、valgrind ,會(huì)跑一個(gè)虛擬機(jī),運(yùn)行時(shí)檢查進(jìn)程的內(nèi)存行為。會(huì)放慢程序的速度。不需要重新編譯程序。
2、addressanitizer,需要重新編譯程序。編譯時(shí)加參數(shù),-fsanitize
gcc 4.9才支持,只會(huì)放慢程序速度2~3倍。
-
Linux
+關(guān)注
關(guān)注
87文章
11350瀏覽量
210466 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3295瀏覽量
57939 -
內(nèi)存泄漏
+關(guān)注
關(guān)注
0文章
39瀏覽量
9239
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論