2021-02-19 分類(lèi): 網(wǎng)站建設(shè)
上一篇我們了解了內(nèi)存在內(nèi)核態(tài)是如何管理的,本篇文章我們一起來(lái)看下內(nèi)存在用戶(hù)態(tài)的使用情況,如果上一篇文章說(shuō)是內(nèi)核驅(qū)動(dòng)工程師經(jīng)常面對(duì)的內(nèi)存管理問(wèn)題,那本篇就是應(yīng)用工程師常面對(duì)的問(wèn)題。
相信大家都知道對(duì)用戶(hù)態(tài)的內(nèi)存消耗對(duì)象是進(jìn)程,應(yīng)用開(kāi)發(fā)者面對(duì)的所有代碼操作最后的落腳點(diǎn)都是進(jìn)程,這也是說(shuō)為什么內(nèi)存和進(jìn)程兩個(gè)知識(shí)點(diǎn)的重要性,理解了內(nèi)存和進(jìn)程兩大法寶,對(duì)所有軟件開(kāi)發(fā)的理解都會(huì)有了全局觀(guān)(關(guān)于進(jìn)程的知識(shí)以后再整理和大家分享)。
下面閑話(huà)少說(shuō),開(kāi)始本篇的內(nèi)容——進(jìn)程的內(nèi)存消耗和泄漏
在linux操作系統(tǒng)中,每個(gè)進(jìn)程都通過(guò)一個(gè)task_struct的結(jié)構(gòu)體描敘,每個(gè)進(jìn)程的地址空間都通過(guò)一個(gè)mm_struct描敘,c語(yǔ)言中的每個(gè)段空間都通過(guò)vm_area_struct表示,他們關(guān)系如下 :
上圖中,task_struct中的mm_struct就代表進(jìn)程的整個(gè)內(nèi)存資源,mm_struct中的pgd為頁(yè)表,mmap指針指向的vm_area_struct鏈表的每一個(gè)節(jié)點(diǎn)就代表進(jìn)程的一個(gè)虛擬地址空間,即一個(gè)VMA。一個(gè)VMA最終可能對(duì)應(yīng)ELF可執(zhí)行程序的數(shù)據(jù)段、代碼段、堆、棧、或者動(dòng)態(tài)鏈接庫(kù)的某個(gè)部分。
VMA的分布情況可以有通過(guò)pmap命令,及maps,smaps文件查看,如下圖:
另,VMA的具體內(nèi)容可參考下圖。
我們先來(lái)看張圖:
(此圖來(lái)源于宋寶華老師)
如,調(diào)用malloc申請(qǐng)100M內(nèi)存,IA32下在0~3G虛擬地址中立刻就會(huì)占用到大小為100M的VMA,且符合堆的定義,這一段VMA的權(quán)限是R+W的。但由于Lazy機(jī)制,這100M其實(shí)并沒(méi)有獲得,這100M全部映射到一個(gè)物理地址相同的零頁(yè),且在頁(yè)表中記錄的權(quán)限為只讀的。當(dāng)100M中任何一頁(yè)發(fā)生寫(xiě)操作時(shí),MMU會(huì)給CPU發(fā)page fault(MMU可以從寄存器讀出發(fā)生page fault的地址;MMU可以讀出發(fā)生page fault的原因),Linux內(nèi)核收到缺頁(yè)中斷,在缺頁(yè)中斷的處理程序中讀出虛擬地址和原因,去VMA中查,發(fā)現(xiàn)是用戶(hù)程序在寫(xiě)malloc的合法區(qū)域且有寫(xiě)權(quán)限,Linux內(nèi)核就真正的申請(qǐng)內(nèi)存,頁(yè)表中對(duì)應(yīng)一頁(yè)的權(quán)限也修改為R+W。
如,程序中有野指針飛到了此程序運(yùn)行時(shí)進(jìn)程的VMA以外的非法區(qū)域,硬件就會(huì)收到page fault,進(jìn)程會(huì)收到SIGSEGV信號(hào)報(bào)段錯(cuò)誤并終止。如,程序中有野指針飛到了此程序運(yùn)行時(shí)進(jìn)程的VMA以外的非法區(qū)域,硬件就會(huì)收到page fault,進(jìn)程會(huì)收到SIGSEGV信號(hào)報(bào)段錯(cuò)誤并終止。
如,代碼段在VMA中權(quán)限為R+X,如果程序中有野指針飛到此區(qū)域去寫(xiě),則也會(huì)發(fā)生段錯(cuò)誤。(另,malloc堆區(qū)在VMA中權(quán)限為R+W,如果程序的PC指針飛到此區(qū)域去執(zhí)行,同樣發(fā)生段錯(cuò)誤。)
如,執(zhí)行代碼段時(shí)會(huì)發(fā)生缺頁(yè),Linux申請(qǐng)1頁(yè)內(nèi)存,并從硬盤(pán)讀取出代碼段,此時(shí)產(chǎn)生了IO操作,為major主缺頁(yè)。如,執(zhí)行代碼段時(shí)會(huì)發(fā)生缺頁(yè),Linux申請(qǐng)1頁(yè)內(nèi)存,并從硬盤(pán)讀取出代碼段,此時(shí)產(chǎn)生了IO操作,為major主缺頁(yè)。
(此圖來(lái)源于宋寶華老師)
綜上,page fault后,Linux會(huì)查VMA,也會(huì)比對(duì)VMA中和頁(yè)表中的權(quán)限,體現(xiàn)出VMA的重要作用。
malloc的過(guò)程其實(shí)就是把VMA分配到各種段當(dāng)中,這時(shí)候是沒(méi)有真正分配物理地址的。malloc 調(diào)用后,只是分配了內(nèi)存的邏輯地址,在內(nèi)核的mm_struct 鏈表中
malloc小于128k的內(nèi)存,使用brk分配內(nèi)存,將_edata往高地址推(只分配虛擬空間,不對(duì)應(yīng)物理內(nèi)存(因此沒(méi)有初始化),第一次讀/寫(xiě)數(shù)據(jù)時(shí),引起內(nèi)核缺頁(yè)中斷,內(nèi)核才分配對(duì)應(yīng)的物理內(nèi)存,然后虛擬地址空間建立映射關(guān)系)
malloc大于128k的內(nèi)存,使用mmap分配內(nèi)存,在堆和棧之間找一塊空閑內(nèi)存分配(對(duì)應(yīng)獨(dú)立內(nèi)存,而且初始化為0)
首先,我們?cè)u(píng)估一個(gè)進(jìn)程的內(nèi)存消耗都是指用戶(hù)空間的內(nèi)存,不包括內(nèi)核空間的內(nèi)存消耗 。這里我們用工具 procrank先來(lái)看下Linux進(jìn)程的內(nèi)存占用量 。
VSS -Virtual Set Size 虛擬耗用內(nèi)存(包含共享庫(kù)占用的內(nèi)存)
RSS -Resident Set Size 實(shí)際使用物理內(nèi)存(包含共享庫(kù)占用的內(nèi)存)
PSS -Proportional Set Size 實(shí)際使用的物理內(nèi)存(比例分配共享庫(kù)占用的內(nèi)存)
USS -Unique Set Size 進(jìn)程獨(dú)自占用的物理內(nèi)存(不包含共享庫(kù)占用的內(nèi)存)
下面再用一張圖來(lái)更好的解釋VSS,RSS,PSS,USS之間的區(qū)別:
有了對(duì)VSS,RSS,PSS,USS的了解,我們趁熱打鐵來(lái)看下內(nèi)存在進(jìn)程中是如何被瓜分的:
(此圖來(lái)源于宋寶華老師)
1044,1045,1054三個(gè)進(jìn)程,每個(gè)進(jìn)程都有一個(gè)頁(yè)表,對(duì)應(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。
一般來(lái)說(shuō)內(nèi)存占用大小有如下規(guī)律:VSS >= RSS >= PSS >= USS
本文名稱(chēng):Linux用戶(hù)態(tài)進(jìn)程的內(nèi)存管理
瀏覽地址:http://m.newbst.com/news8/101808.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、網(wǎng)站導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)、建站公司、響應(yīng)式網(wǎng)站、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容