日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

上一篇我們了解了內存在內核態是如何管理的,本篇文章我們一起來看下內存在用戶態的使用情況,如果上一篇文章說是內核驅動工程師經常面對的內存管理問題,那本篇就是應用工程師常面對的問題。

相信大家都知道對用戶態的內存消耗對象是進程,應用開發者面對的所有代碼操作最后的落腳點都是進程,這也是說為什么內存和進程兩個知識點的重要性,理解了內存和進程兩大法寶,對所有軟件開發的理解都會有了全局觀(關于進程的知識以后再整理和大家分享)。

下面閑話少說,開始本篇的內容——進程的內存消耗和泄漏

 

進程的虛擬地址空間VMA(Virtual Memory Area)

在linux操作系統中,每個進程都通過一個task_struct的結構體描敘,每個進程的地址空間都通過一個mm_struct描敘,C語言中的每個段空間都通過vm_area_struct表示,他們關系如下 :

Linux用戶態進程的內存管理

上圖中,task_struct中的mm_struct就代表進程的整個內存資源,mm_struct中的pgd為頁表,mmap指針指向的vm_area_struct鏈表的每一個節點就代表進程的一個虛擬地址空間,即一個VMA。一個VMA最終可能對應ELF可執行程序的數據段、代碼段、堆、棧、或者動態鏈接庫的某個部分。

VMA的分布情況可以有通過pmap命令,及maps,smaps文件查看,如下圖:

Linux用戶態進程的內存管理

另,VMA的具體內容可參考下圖。

Linux用戶態進程的內存管理

 

page fault的幾種可能性

我們先來看張圖:

Linux用戶態進程的內存管理

(此圖來源于宋寶華老師)

  • 如,調用malloc申請100M內存,IA32下在0~3G虛擬地址中立刻就會占用到大小為100M的VMA,且符合堆的定義,這一段VMA的權限是R+W的。但由于Lazy機制,這100M其實并沒有獲得,這100M全部映射到一個物理地址相同的零頁,且在頁表中記錄的權限為只讀的。當100M中任何一頁發生寫操作時,MMU會給CPU發page fault(MMU可以從寄存器讀出發生page fault的地址;MMU可以讀出發生page fault的原因),Linux內核收到缺頁中斷,在缺頁中斷的處理程序中讀出虛擬地址和原因,去VMA中查,發現是用戶程序在寫malloc的合法區域且有寫權限,Linux內核就真正的申請內存,頁表中對應一頁的權限也修改為R+W。

  • 如,程序中有野指針飛到了此程序運行時進程的VMA以外的非法區域,硬件就會收到page fault,進程會收到SIGSEGV信號報段錯誤并終止。如,程序中有野指針飛到了此程序運行時進程的VMA以外的非法區域,硬件就會收到page fault,進程會收到SIGSEGV信號報段錯誤并終止。

  • 如,代碼段在VMA中權限為R+X,如果程序中有野指針飛到此區域去寫,則也會發生段錯誤。(另,malloc堆區在VMA中權限為R+W,如果程序的PC指針飛到此區域去執行,同樣發生段錯誤。)

  • 如,執行代碼段時會發生缺頁,Linux申請1頁內存,并從硬盤讀取出代碼段,此時產生了IO操作,為major主缺頁。如,執行代碼段時會發生缺頁,Linux申請1頁內存,并從硬盤讀取出代碼段,此時產生了IO操作,為major主缺頁。

Linux用戶態進程的內存管理

(此圖來源于宋寶華老師)

綜上,page fault后,Linux會查VMA,也會比對VMA中和頁表中的權限,體現出VMA的重要作用。

 

malloc分配的原理

malloc的過程其實就是把VMA分配到各種段當中,這時候是沒有真正分配物理地址的。malloc 調用后,只是分配了內存的邏輯地址,在內核的mm_struct 鏈表中插入vm_area_struct結構體,沒有分配實際的內存。當分配的區域寫入數據是,引發頁中斷,建立物理頁和邏輯地址的映射。下圖表示了這個過程。

Linux用戶態進程的內存管理

從操作系統角度來看,進程分配內存有兩種方式,分別由兩個系統調用完成:brk和mmap(不考慮共享內存)。

  • malloc小于128k的內存,使用brk分配內存,將_edata往高地址推(只分配虛擬空間,不對應物理內存(因此沒有初始化),第一次讀/寫數據時,引起內核缺頁中斷,內核才分配對應的物理內存,然后虛擬地址空間建立映射關系)

  • malloc大于128k的內存,使用mmap分配內存,在堆和棧之間找一塊空閑內存分配(對應獨立內存,而且初始化為0)

 

內存的消耗VSS RSS PSS USS

首先,我們評估一個進程的內存消耗都是指用戶空間的內存,不包括內核空間的內存消耗 。這里我們用工具 procrank先來看下Linux進程的內存占用量 。

Linux用戶態進程的內存管理
  • VSS -Virtual Set Size 虛擬耗用內存(包含共享庫占用的內存)

  • RSS -Resident Set Size 實際使用物理內存(包含共享庫占用的內存)

  • PSS -Proportional Set Size 實際使用的物理內存(比例分配共享庫占用的內存)

  • USS -Unique Set Size 進程獨自占用的物理內存(不包含共享庫占用的內存)

下面再用一張圖來更好的解釋VSS,RSS,PSS,USS之間的區別:

Linux用戶態進程的內存管理

有了對VSS,RSS,PSS,USS的了解,我們趁熱打鐵來看下內存在進程中是如何被瓜分的:

Linux用戶態進程的內存管理

(此圖來源于宋寶華老師)

1044,1045,1054三個進程,每個進程都有一個頁表,對應其虛擬地址如何向real memory上去轉換。

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三個進程都使用了libc的代碼段,被三個進程分享。

5 bash shell的代碼段,1044,1045都是bash shell,被兩個進程分享。

6 1044獨占

所以,上圖中4+5+6并不全是1044進程消耗的內存,因為4明顯被3個進程指向,5明顯被2個進程指向,衍生出了PSS(按比例計算的駐留內存)的概念。進程1044的PSS為4/3 +5/2 +6。

最后,進程1044獨占且駐留的內存USS為 6。

一般來說內存占用大小有如下規律:VSS >= RSS >= PSS >= USS

【部分內容整理于宋寶華老師課程】

分享到:
標簽:內存管理 Linux
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定