Linux內(nèi)存管理 -- /proc/{pid}/smaps講解

本文包括如下三部分:

  1. 基本介紹與輸出介紹
  2. 第一行基礎(chǔ)信息講解
  3. 詳細(xì)信息講解
    3.1 Size
    3.2 Rss
    3.3 Pss、Shared/Private_Clean/Dirty
    3.4 Referenced
    3.5 Anonymous
    3.6 ShmemPmdMapped
    3.7 Shared/Private_Hugetlb
    3.8 Swap
    3.9 SwapPss
    3.10 KernelPageSize、MMUPageSize
    3.11 Locked
    3.12 THPeligible
    3.13 VmFlags

如果對(duì)Linux的內(nèi)存管理機(jī)制沒(méi)有了解過(guò),建議先了解一下,便于理解:Linux內(nèi)存管理

基本介紹

/proc/PID/smaps 文件是基于 /proc/PID/maps 的擴(kuò)展,他展示了一個(gè)進(jìn)程的內(nèi)存消耗,比同一目錄下的maps文件更為詳細(xì)。

值得說(shuō)明一下的是,每一個(gè)VMA(虛擬內(nèi)存區(qū)域,即一個(gè) vm_area_struct 結(jié)構(gòu)指向的內(nèi)存區(qū)域)都有如下的一系列數(shù)據(jù)

08048000-080bc000 r-xp 00000000 03:02 13130      /bin/bash

Size:               1084 kB
Rss:                 892 kB
Pss:                 374 kB
Shared_Clean:        892 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:          892 kB
Anonymous:             0 kB
ShmemPmdMapped:        0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
THPeligible:           0
VmFlags: rd ex mr mw me dw

第一行基礎(chǔ)信息

在講解字段含義之前,我們必須知道什么匿名映射
Linux 內(nèi)存管理的進(jìn)程用戶態(tài)內(nèi)存分布中提到過(guò),映射分為文件映射和匿名映射。

文件映射就是磁盤中的數(shù)據(jù)通過(guò)文件系統(tǒng)映射到內(nèi)存再通過(guò)文件映射映射到虛擬空間,這樣,用戶就可以在用戶空間通過(guò) open ,read, write 等函數(shù)區(qū)操作文件內(nèi)容。至于實(shí)際的代碼,open,read,write,close,mmap... 操作的虛擬地址都屬于文件映射。

匿名映射就是用戶空間需要分配一定的物理內(nèi)存來(lái)存儲(chǔ)數(shù)據(jù),這部分內(nèi)存不屬于任何文件,內(nèi)核就使用匿名映射將內(nèi)存中的某段物理地址與用戶空間一一映射,這樣用戶就可用直接操作虛擬地址來(lái)范圍這段物理內(nèi)存。比如使用malloc申請(qǐng)內(nèi)存。

  • 08048000-080bc000 是該虛擬內(nèi)存段的開(kāi)始和結(jié)束位置
  • r-xp 內(nèi)存段的權(quán)限,分別是可讀、可寫、可運(yùn)行、私有或共享,最后一位p代表私有,s代表共享
  • 00000000 該虛擬內(nèi)存段起始地址在對(duì)應(yīng)的映射文件中以頁(yè)為單位的偏移量,對(duì)匿名映射,它等于0或者vm_start/PAGE_SIZE
  • 03:02 文件的主設(shè)備號(hào)和次設(shè)備號(hào)。對(duì)匿名映射來(lái)說(shuō),因?yàn)闆](méi)有文件在磁盤上,所以沒(méi)有設(shè)備號(hào),始終為00:00。對(duì)有名映射來(lái)說(shuō),是映射的文件所在設(shè)備的設(shè)備號(hào)。
  • 13130 被映射到虛擬內(nèi)存的文件的索引節(jié)點(diǎn)號(hào),通過(guò)該節(jié)點(diǎn)可以找到對(duì)應(yīng)的文件,對(duì)匿名映射來(lái)說(shuō),因?yàn)闆](méi)有文件在磁盤上,所以沒(méi)有節(jié)點(diǎn)號(hào),始終為00:00。
  • /bin/bash 被映射到虛擬內(nèi)存的文件名稱。后面帶(deleted)的是內(nèi)存數(shù)據(jù),可以被銷毀。對(duì)有名來(lái)說(shuō),是映射的文件名。對(duì)匿名映射來(lái)說(shuō),是此段虛擬內(nèi)存在進(jìn)程中的角色。[stack]表示在進(jìn)程中作為棧使用,[heap]表示堆。其余情況則無(wú)顯示。

第一行的信息完全同于在maps文件中輸出的信息。對(duì)于不熟悉maps文件的讀者可以先了解maps的字段的含義與實(shí)現(xiàn)機(jī)制。

詳細(xì)信息

Size虛擬內(nèi)存空間大小。但是這個(gè)內(nèi)存值不一定是物理內(nèi)存實(shí)際分配的大小,因?yàn)樵谟脩魬B(tài)上,虛擬內(nèi)存總是延遲分配的。這個(gè)值計(jì)算也非常簡(jiǎn)單,就是該VMA的開(kāi)始位置減結(jié)束位置

延遲分配就是當(dāng)進(jìn)程申請(qǐng)內(nèi)存的時(shí)候,Linux會(huì)給他先分配頁(yè),但是并不會(huì)區(qū)建立頁(yè)與頁(yè)框的映射關(guān)系,意思就是說(shuō)并不會(huì)分配物理內(nèi)存,而當(dāng)真正使用的時(shí)候,就會(huì)產(chǎn)生一個(gè)缺頁(yè)異常,硬件跳轉(zhuǎn)page fault處理程序執(zhí)行,在其中分配物理內(nèi)存,然后修改頁(yè)表(創(chuàng)建頁(yè)表項(xiàng))。異常處理完畢,返回程序用戶態(tài),繼續(xù)執(zhí)行。

Rss:是實(shí)際分配的內(nèi)存,這部分物理內(nèi)存已經(jīng)分配,不需要缺頁(yè)中斷就可以使用的。
這里有一個(gè)公式計(jì)算Rss:
Rss=Shared_Clean+Shared_Dirty+Private_Clean+Private_Dirty

share/private:該頁(yè)面是共享還是私有。
dirty/clean:該頁(yè)面是否被修改過(guò),如果修改過(guò)(dirty),在頁(yè)面被淘汰的時(shí)候,就會(huì)把該臟頁(yè)面回寫到交換分區(qū)(換出,swap out)。有一個(gè)標(biāo)志位用于表示頁(yè)面是否dirty。

share/private_dirty/clean 計(jì)算邏輯:
查看該page的引用數(shù),如果引用>1,則歸為shared,如果是1,則歸為private,同時(shí)也查看該page的flag,是否標(biāo)記為_(kāi)PAGE_DIRTY,如果不是,則認(rèn)為干凈的。

Pss(proportional set size):是平攤計(jì)算后的實(shí)際物理使用內(nèi)存(有些內(nèi)存會(huì)和其他進(jìn)程共享,例如mmap進(jìn)來(lái)的)。實(shí)際上包含下面private_clean+private_dirty,和按比例均分的shared_clean、shared_dirty。

舉個(gè)計(jì)算Pss的例子:
如果進(jìn)程A有x個(gè)private_clean頁(yè)面,有y個(gè)private_dirty頁(yè)面,有z個(gè)shared_clean僅和進(jìn)程B共享,有h個(gè)shared_dirty頁(yè)面和進(jìn)程B、C共享。那么進(jìn)程A的Pss為:
x + y + z/2 + h/3

Referenced:當(dāng)前頁(yè)面被標(biāo)記為已引用或者包含匿名映射(The amount of memory currently marked as referenced or a mapping associated with a file may contain anonymous pages)。

Linux內(nèi)存管理的頁(yè)面替換算法里講過(guò),當(dāng)某個(gè)頁(yè)面被訪問(wèn)后,Referenced標(biāo)志被設(shè)置,如果該標(biāo)志設(shè)置了,就 不能將該頁(yè)移出。

Anonymous:匿名映射的物理內(nèi)存,這部分內(nèi)存不來(lái)自于文件的內(nèi)存大小。

ShmemPmdMapped:PMD頁(yè)面已經(jīng)被映射的共享(shmem / tmpfs)內(nèi)存量。在官方文檔中,這樣解釋:"ShmemPmdMapped" shows the ammount of shared (shmem/tmpfs) memory backed by huge pages.

Shared/Private_Hugetlb:由hugetlbfs頁(yè)面支持的內(nèi)存使用量,由于歷史原因,該頁(yè)面未計(jì)入“ RSS”或“ PSS”字段中。 并且這些沒(méi)有包含在Shared/Private_Clean/Dirty 字段中。

Swap:存在于交換分區(qū)的數(shù)據(jù)大小(如果物理內(nèi)存有限,可能存在一部分在主存一部分在交換分區(qū))

SwapPss:這個(gè)我并沒(méi)有找到對(duì)應(yīng)解釋,但從源碼可以得知,計(jì)算邏輯就跟pss一樣,只不過(guò)針對(duì)的是交換分區(qū)的內(nèi)存。

static void smaps_pte_entry(pte_t *pte, unsigned long addr,
        struct mm_walk *walk)
{
    struct mem_size_stats *mss = walk->private;
    struct vm_area_struct *vma = walk->vma;
    struct page *page = NULL;

    if (pte_present(*pte)) {//----------------------------------頁(yè)面在內(nèi)存中
        page = vm_normal_page(vma, addr, *pte);
    } else if (is_swap_pte(*pte)) {//---------------------------頁(yè)面被swap出
        swp_entry_t swpent = pte_to_swp_entry(*pte);

        if (!non_swap_entry(swpent)) {
            int mapcount;

            mss->swap += PAGE_SIZE;
            mapcount = swp_swapcount(swpent);
            if (mapcount >= 2) {
                u64 pss_delta = (u64)PAGE_SIZE << PSS_SHIFT;
               do_div(pss_delta, mapcount);
                mss->swap_pss += pss_delta; // --------- 如果引用超過(guò)1,就將均值加入swap_pss中
            } else {
                mss->swap_pss += (u64)PAGE_SIZE << PSS_SHIFT;// ------------ 直接加一個(gè)頁(yè)大小
            }
       } else if (is_migration_entry(swpent))
            page = migration_entry_to_page(swpent);
    }

    if (!page)//----------------------------------------------如果頁(yè)面不存在,就不用更新mss其他信息了;如果存在,調(diào)用smaps_account()更新mss。
        return;
smaps_account(mss, page, PAGE_SIZE, pte_young(*pte), pte_dirty(*pte));
}

KernelPageSize:內(nèi)核一頁(yè)的大小
MMUPageSize:MMU頁(yè)大小,大多數(shù)情況下,和KernelPageSize大小一樣。

Locked:常駐物理內(nèi)存的大小,這些頁(yè)不會(huì)被換出。

THPeligible:映射是否符合分配THP的條件。如果為true,則為1,否則為0。 它僅顯示當(dāng)前狀態(tài)。

THP,透明大頁(yè)(Transparent Huge Pages),RHEL 6 開(kāi)始引入,目的是使用更大的內(nèi)存頁(yè)面(memory page size) 以適應(yīng)越來(lái)越大的系統(tǒng)內(nèi)存,讓操作系統(tǒng)可以支持現(xiàn)代硬件架構(gòu)的大頁(yè)面容量功能。與標(biāo)準(zhǔn)大頁(yè)的區(qū)別在于分配機(jī)制,標(biāo)準(zhǔn)大頁(yè)管理是預(yù)分配的方式,而透明大頁(yè)管理則是動(dòng)態(tài)分配的方式。

VmFlags:表示與特定虛擬內(nèi)存區(qū)域關(guān)聯(lián)的內(nèi)核標(biāo)志。標(biāo)志如下:

rd  - readable
wr  - writeable
ex  - executable
sh  - shared
mr  - may read
mw  - may write
me  - may execute
ms  - may share
gd  - stack segment growns down
pf  - pure PFN range
dw  - disabled write to the mapped file
lo  - pages are locked in memory
io  - memory mapped I/O area
sr  - sequential read advise provided
rr  - random read advise provided
dc  - do not copy area on fork
de  - do not expand area on remapping
ac  - area is accountable
nr  - swap space is not reserved for the area
ht  - area uses huge tlb pages
ar  - architecture specific flag
dd  - do not include area into core dump
sd  - soft-dirty flag
mm  - mixed map area
hg  - huge page advise flag
nh  - no-huge page advise flag
mg  - mergable advise flag

參考文章:
Linux官方文檔
Linux smaps接口文件結(jié)構(gòu)
linux proc maps文件分析
linux proc maps文件分析
匿名文件映射問(wèn)題 (概念不清晰)
Linux中各種設(shè)備及設(shè)備號(hào)
Linux smaps接口文件結(jié)構(gòu)
閑聊Linux內(nèi)存管理(1)
Linux物理內(nèi)存回收機(jī)制
Linux /proc/$pid/smaps的含義
Linux傳統(tǒng)Huge Pages與Transparent Huge Pages再次學(xué)習(xí)總結(jié)
Linux內(nèi)存管理 一個(gè)進(jìn)程究竟占用多少空間?-VSS/RSS/PSS/USS
linux 內(nèi)存查看方法:meminfo\maps\smaps\status 文件解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 175,870評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,742評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,527評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,010評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,250評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,656評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,853評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,103評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,472評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,717評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,487評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,815評(píng)論 2 372