0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux進(jìn)程的內(nèi)存消耗和泄漏詳解

書(shū)生途 ? 來(lái)源:書(shū)生途 ? 作者:書(shū)生途 ? 2022-05-14 10:07 ? 次閱讀

內(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ù)段寫(xiě)時(shí)拷貝。
把一個(gè)應(yīng)用程序跑兩個(gè)進(jìn)程,這兩個(gè)進(jìn)程的代碼段也是共享的。

當(dāng)我們?cè)u(píng)估進(jìn)程消耗多少內(nèi)存時(shí),就是指在用戶(hù)空間消耗的內(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

poYBAGJ-ZoSAXn1TAABu5WwG4Z0259.jpg

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之間任意分布的。

pYYBAGJ-ZoSAYInyAAEgNvLwiU4140.jpg

上圖 提供三種方式,看到進(jìn)程的VMA空間。pmap 3474其地址,size, 權(quán)限,通過(guò)以上的方式,可以看到進(jìn)程的虛擬地址空間,分布在0~3G,任意一小段一小段分布的。應(yīng)用程序運(yùn)行起來(lái),就是一堆各種各樣的VMA。VMA對(duì)應(yīng)著 堆、棧、代碼段、數(shù)據(jù)段、等,不在任何段里的虛擬地址空間,被認(rèn)為是非法的。

poYBAGJ-ZoWAKppBAACpvXNELgQ800.jpg

當(dāng)指針訪問(wèn)地址時(shí),落在一個(gè)非法的地址,即不在任何一個(gè)VMA區(qū)域。相當(dāng)于訪問(wèn)一個(gè)非法的地址,這些虛擬地址沒(méi)有對(duì)應(yīng)的物理地址。應(yīng)用程序收到page fault,查看原因,訪問(wèn)非法位置,返回segv。

在VMA的東西,不等于在內(nèi)存。調(diào)malloc申請(qǐng)了100M內(nèi)存,立馬會(huì)多出一個(gè)100M的 VMA,代表這段vma區(qū)域有r+w權(quán)限。

應(yīng)用程序訪問(wèn)內(nèi)存,必須落在一個(gè)VMA里。其次,落在一個(gè)VMA里也不一定對(duì)。把100M的堆申請(qǐng)出來(lái),100M內(nèi)存頁(yè)全部映射為0頁(yè)。頁(yè)表里每一頁(yè)寫(xiě)的只讀,頁(yè)表和硬件對(duì)應(yīng),MMU只查頁(yè)表。而在頁(yè)表項(xiàng)中指向物理地址的權(quán)限是只讀,所以在任何時(shí)候,去寫(xiě)其中任何一頁(yè),硬件都會(huì)發(fā)生缺頁(yè)中斷。

Linux 內(nèi)核在缺頁(yè)中斷的處理程序,通過(guò)MMU寄存器讀出發(fā)生page fault的地址和原因。發(fā)現(xiàn)此時(shí)page fault的原因是寫(xiě)一個(gè)頁(yè)表里記錄只讀的物理地址,而vma記錄的虛擬地址又是r+w,此時(shí),linux會(huì)申請(qǐng)一頁(yè)內(nèi)存。同時(shí)把頁(yè)表中的權(quán)限改為r+w。

總結(jié):
Linux 內(nèi)核通過(guò)VMA管理進(jìn)程每一段虛擬地址空間和權(quán)限。一旦發(fā)生page fault,如果沒(méi)有落在任何一個(gè)vma區(qū)域,會(huì)干掉。VMA的起始地址+size,用來(lái)限定程序訪問(wèn)的地址是否合法。VMA中每一段的權(quán)限,是來(lái)界定訪問(wèn)這段地址是否使用正確的方式訪問(wèn)。把所有的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。

pYYBAGJ-ZoWAB9mRAAC8kOW-Vl0528.jpg


1、申請(qǐng)堆內(nèi)存vma,第一次寫(xiě),頁(yè)表里的權(quán)限是R ,發(fā)生page fault,linux會(huì)去申請(qǐng)一頁(yè)內(nèi)存,此時(shí)把頁(yè)表權(quán)限設(shè)置為 R+W。
2、內(nèi)存訪問(wèn)落在空白非法區(qū)域,程序收到segv段錯(cuò)誤。
3、代碼段在VMA記錄是R+X,此時(shí)如果對(duì)代碼段執(zhí)行寫(xiě),程序會(huì)收到segv段錯(cuò)誤。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【865977150】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!!

poYBAGJ-ZoWAfnjtAADZ9NmCySQ141.jpg

內(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í),是否需要讀硬盤(pán)。前者需要。

如上圖第4種情況,在代碼段里執(zhí)行時(shí),出現(xiàn)缺頁(yè)。linux申請(qǐng)一頁(yè)內(nèi)存,而且要從硬盤(pán)中讀取代碼段的內(nèi)容,此時(shí)產(chǎn)生了IO,稱(chēng)為 major缺頁(yè)。

無(wú)論是代碼段還是堆,都是邊執(zhí)行邊產(chǎn)生缺頁(yè)中斷,申請(qǐng)實(shí)際的內(nèi)存給代碼段,且從硬盤(pán)中讀取代碼段的內(nèi)容到內(nèi)存。這個(gè)過(guò)程時(shí)間比較長(zhǎng)。

minor: malloc的內(nèi)存,產(chǎn)生缺頁(yè)中斷。去申請(qǐng)一頁(yè)內(nèi)存,沒(méi)有產(chǎn)生IO的行為。major缺頁(yè)處理時(shí)間,遠(yuǎn)大于minor。

pYYBAGJ-ZoWAfBNwAACJx5wvbds660.jpg

vss、rss、pss和uss的區(qū)別

poYBAGJ-ZoWAKXSbAACZ-PvEwcw068.jpg
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è)表也跟著一起切換。

pYYBAGJ-ZoWAALXWAAC2Kx1EUOU143.jpg

三個(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倍。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11123

    瀏覽量

    207906
  • 應(yīng)用程序
    +關(guān)注

    關(guān)注

    37

    文章

    3198

    瀏覽量

    57360
  • 內(nèi)存泄漏
    +關(guān)注

    關(guān)注

    0

    文章

    39

    瀏覽量

    9185
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux內(nèi)存管理是什么,Linux內(nèi)存管理詳解

    Linux內(nèi)存管理 Linux內(nèi)存管理是一個(gè)非常復(fù)雜的過(guò)程,主要分成兩個(gè)大的部分:內(nèi)核的內(nèi)存管理和進(jìn)
    的頭像 發(fā)表于 05-11 17:54 ?5827次閱讀
    <b class='flag-5'>Linux</b>的<b class='flag-5'>內(nèi)存</b>管理是什么,<b class='flag-5'>Linux</b>的<b class='flag-5'>內(nèi)存</b>管理<b class='flag-5'>詳解</b>

    Linux內(nèi)存泄漏檢測(cè)實(shí)現(xiàn)原理與實(shí)現(xiàn)

    在使用沒(méi)有垃圾回收的語(yǔ)言時(shí)(如 C/C++),可能由于忘記釋放內(nèi)存而導(dǎo)致內(nèi)存被耗盡,這叫 內(nèi)存泄漏。由于內(nèi)核也需要自己管理內(nèi)存,所以也可能出
    發(fā)表于 12-09 11:11 ?931次閱讀

    Linux進(jìn)程間如何實(shí)現(xiàn)共享內(nèi)存通信

    這次我們來(lái)講一下Linux進(jìn)程通信中重要的通信方式:共享內(nèi)存作為Linux軟件開(kāi)發(fā)攻城獅,進(jìn)程間通信是必須熟練掌握的重要技能,而共享
    發(fā)表于 04-26 17:14 ?639次閱讀

    細(xì)說(shuō)Linux內(nèi)存泄漏檢測(cè)實(shí)現(xiàn)原理與實(shí)現(xiàn)

    在使用沒(méi)有垃圾回收的語(yǔ)言時(shí)(如 C/C++),可能由于忘記釋放內(nèi)存而導(dǎo)致內(nèi)存被耗盡,這叫 內(nèi)存泄漏。由于內(nèi)核也需要自己管理內(nèi)存,所以也可能出
    發(fā)表于 07-03 09:22 ?417次閱讀
    細(xì)說(shuō)<b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>泄漏</b>檢測(cè)實(shí)現(xiàn)原理與實(shí)現(xiàn)

    Linux內(nèi)核內(nèi)存泄漏怎么辦

    Linux內(nèi)核開(kāi)發(fā)中,Kmemleak是一種用于檢測(cè)內(nèi)核中內(nèi)存泄漏的工具。
    發(fā)表于 07-04 11:04 ?718次閱讀

    Linux進(jìn)程間通信——使用共享內(nèi)存

    Linux進(jìn)程間通信——使用共享內(nèi)存 圖文詳情見(jiàn)附件
    發(fā)表于 11-21 10:53

    Linux上對(duì)進(jìn)程進(jìn)行內(nèi)存分析和內(nèi)存泄漏定位

    Linux產(chǎn)品開(kāi)發(fā)過(guò)程中,通常需要注意系統(tǒng)內(nèi)存使用量,和評(píng)估單一進(jìn)程內(nèi)存使用情況,便于我們選取合適的機(jī)器配置,來(lái)部署我們的產(chǎn)品。Linux
    發(fā)表于 07-09 08:15

    Linux守護(hù)進(jìn)程詳解

    分享到:標(biāo)簽:進(jìn)程控制 Linux 守護(hù)進(jìn)程進(jìn)程 7.3 Linux守護(hù)進(jìn)程 7.3.1 守
    發(fā)表于 10-18 14:24 ?0次下載
    <b class='flag-5'>Linux</b>守護(hù)<b class='flag-5'>進(jìn)程</b><b class='flag-5'>詳解</b>

    Linux進(jìn)程內(nèi)存結(jié)構(gòu)

    Linux操作系統(tǒng)采用虛擬內(nèi)存管理技術(shù),使得每個(gè)進(jìn)程都有各自互不干涉的進(jìn)程地址空間。該地址空間是大小為4GB的線性虛擬空間,用戶(hù)所看到和接觸到的都是該虛擬地址,無(wú)法看到實(shí)際的物理
    發(fā)表于 06-01 09:17 ?1432次閱讀
    <b class='flag-5'>Linux</b>下<b class='flag-5'>進(jìn)程</b>的<b class='flag-5'>內(nèi)存</b>結(jié)構(gòu)

    Linux:測(cè)試進(jìn)程占用的虛擬內(nèi)存大小

    Linux:測(cè)試進(jìn)程占用的虛擬內(nèi)存大小
    的頭像 發(fā)表于 06-23 09:23 ?2771次閱讀
    <b class='flag-5'>Linux</b>:測(cè)試<b class='flag-5'>進(jìn)程</b>占用的虛擬<b class='flag-5'>內(nèi)存</b>大小

    Linux內(nèi)核內(nèi)存泄漏怎么辦?

    什么是內(nèi)存泄漏: 程序向系統(tǒng)申請(qǐng)內(nèi)存,使用完不需要之后,不釋放內(nèi)存還給系統(tǒng)回收,造成申請(qǐng)的內(nèi)存被浪費(fèi). 發(fā)現(xiàn)系統(tǒng)中
    的頭像 發(fā)表于 02-20 17:14 ?2459次閱讀
    <b class='flag-5'>Linux</b>內(nèi)核<b class='flag-5'>內(nèi)存</b><b class='flag-5'>泄漏</b>怎么辦?

    Linux內(nèi)核源碼分析-進(jìn)程的哪些內(nèi)存類(lèi)型容易引起內(nèi)存泄漏?

    ; 應(yīng)用程序正在運(yùn)行時(shí)忽然被 OOM kill 掉了; 進(jìn)程看起來(lái)沒(méi)有消耗多少內(nèi)存,但是系統(tǒng)內(nèi)存就是不夠用了; ……類(lèi)似問(wèn)題,很可能就是內(nèi)存
    發(fā)表于 01-14 13:02 ?6次下載
    <b class='flag-5'>Linux</b>內(nèi)核源碼分析-<b class='flag-5'>進(jìn)程</b>的哪些<b class='flag-5'>內(nèi)存</b>類(lèi)型容易引起<b class='flag-5'>內(nèi)存</b><b class='flag-5'>泄漏</b>?

    什么是內(nèi)存泄漏內(nèi)存泄漏有哪些現(xiàn)象

    內(nèi)存泄漏幾乎是很難避免的,不管是老手還是新手,都存在這個(gè)問(wèn)題,甚至 Windows 與 Linux 這類(lèi)系統(tǒng)軟件也或多或少存在著內(nèi)存泄漏
    的頭像 發(fā)表于 09-05 17:24 ?9476次閱讀

    Linux系統(tǒng)的共享內(nèi)存的使用

    但有時(shí)候?yàn)榱俗尣煌?b class='flag-5'>進(jìn)程之間進(jìn)行通信,需要讓不同進(jìn)程共享相同的物理內(nèi)存,Linux通過(guò) 共享內(nèi)存 來(lái)實(shí)現(xiàn)這個(gè)功能。下面先來(lái)介紹一下
    的頭像 發(fā)表于 11-14 11:55 ?1189次閱讀

    線程內(nèi)存泄漏問(wèn)題的定位

    在下降。確定內(nèi)存泄漏確實(shí)存在。top中可以顯示多種形式內(nèi)存,進(jìn)而可以判斷是那種泄漏。比如vss/rss/pss等。 確定哪個(gè)進(jìn)程
    的頭像 發(fā)表于 11-13 11:38 ?509次閱讀
    線程<b class='flag-5'>內(nèi)存</b><b class='flag-5'>泄漏</b>問(wèn)題的定位