在top命令的結(jié)果中,有一個(gè)VIRT 的輸出項(xiàng),這個(gè)項(xiàng)的官方解釋如下:
VIRT -- Virtual Memory Size (KiB)
The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been
swapped out and pages that have been mapped but not used.
從字面理解,就是一個(gè)task占用的虛擬內(nèi)存的大小,包括代碼,數(shù)據(jù),共享庫(kù),swap out的pages,以及mapped 了但是還沒(méi)有used 的pages.
而我們已經(jīng)知道,這里page的概念其實(shí)是內(nèi)存的“頁(yè)”,內(nèi)存采用分頁(yè)機(jī)制;所以,簡(jiǎn)單來(lái)說(shuō),VIRT就是代碼,數(shù)據(jù),共享庫(kù)以及map為內(nèi)存可以訪問(wèn)的其他數(shù)據(jù),無(wú)論這些數(shù)據(jù)是在物理內(nèi)存還是在虛擬內(nèi)存,只要是已經(jīng)Map為內(nèi)存可以訪問(wèn)的,那么都算數(shù). 那具體來(lái)說(shuō),上述的數(shù)據(jù)都map了哪些文件,哪些內(nèi)存地址呢? 其實(shí)可以在 proc 中找出的;
先說(shuō)結(jié)論,然后做個(gè)簡(jiǎn)單的驗(yàn)證:
VIRT的大小,等于/proc/maps的大小的綜合,而map對(duì)應(yīng)的文件的大小,可以通過(guò) /proc/map_files進(jìn)行計(jì)算,這個(gè)值和maps 中的文件相關(guān)項(xiàng)計(jì)算出來(lái)的大小是一致的,而剩下的非文件相關(guān)的則是: heap, stack ...,也就是說(shuō)VIRT的大小,其實(shí)就是已經(jīng)map的文件的大小加上堆,棧, 以及其他的空間等;而其他空間則主要是堆空間的大小,另外還有棧空間...
驗(yàn)證過(guò)程如下:
- 在/proc/{PID}/maps 下面,就表示當(dāng)前的task已經(jīng)進(jìn)了map的地址空間,我們可以驗(yàn)證下這些空間總的大小,默認(rèn)是KB,方法如下:
root:8094# head maps #我們看這個(gè)文件的前10行內(nèi)容,其中第一列就是map的內(nèi)存地址空間;
55f319b10000-55f319dc8000 r-xp 00000000 fd:02 403346422 /usr/bin/vim
55f319fc7000-55f319fd6000 r--p 002b7000 fd:02 403346422 /usr/bin/vim
55f319fd6000-55f319ff0000 rw-p 002c6000 fd:02 403346422 /usr/bin/vim
55f319ff0000-55f31a000000 rw-p 00000000 00:00 0
55f31b7f6000-55f31bb35000 rw-p 00000000 00:00 0 [heap]
7fbf0b2fa000-7fbf0b305000 r-xp 00000000 fd:02 960898 /usr/lib64/libnss_files-2.28.so
7fbf0b305000-7fbf0b505000 ---p 0000b000 fd:02 960898 /usr/lib64/libnss_files-2.28.so
7fbf0b505000-7fbf0b506000 r--p 0000b000 fd:02 960898 /usr/lib64/libnss_files-2.28.so
7fbf0b506000-7fbf0b507000 rw-p 0000c000 fd:02 960898 /usr/lib64/libnss_files-2.28.so
7fbf0b507000-7fbf0b50d000 rw-p 00000000 00:00 0
root:8094# cat maps | awk '{print $1}' | awk -F'[-]' '{s=strtonum("0x"$1);e=strtonum("0x"$2);sum+=e-s}END{print sum/1024}' #計(jì)算maps下總的已經(jīng)map的大??;單位是KB.
257600
- 看下top 下該進(jìn)程占用的空間大小:
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 6.8 us, 3.2 sy, 0.0 ni, 88.7 id, 0.0 wa, 0.8 hi, 0.5 si, 0.0 st
MiB Mem : 7704.4 total, 2043.3 free, 2798.0 used, 2863.1 buff/cache
MiB Swap: 7708.0 total, 7708.0 free, 0.0 used. 4025.6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8094 root 20 0 257596 9128 5508 S 0.0 0.1 0:00.06 vim
- 對(duì)于兩者之間的差距,top 顯示VIRT是257596, 而 cat /proc/8094/maps ,然后計(jì)算得到的結(jié)果是257600, 剛好相差一個(gè)4KB,這個(gè)是一個(gè)PAGE, 出現(xiàn)這個(gè)的原因是page 對(duì)齊導(dǎo)致的;在實(shí)際的map過(guò)程中,因?yàn)閷?duì)齊的原因,所以占用的實(shí)際空間多了一個(gè)PAGE, 在這個(gè)例子中是一個(gè)PAGE, 不一定在其他的例子中也是一個(gè)PAGE,但是應(yīng)該都是4KB的整數(shù)倍;
- 計(jì)算/proc/{PID}/file_maps下map的空間大小,可以發(fā)現(xiàn)這個(gè)大小和 maps下的文件相關(guān)的大小是一致的;
- 堆空間不一定是連續(xù)的,而??臻g則是連續(xù)的;堆空間依靠函數(shù)調(diào)用來(lái)申請(qǐng),而??臻g則系統(tǒng)自動(dòng)管理;用戶程序代碼申請(qǐng)的空間一般都是堆空間;
上述的/proc/maps 描述了map的大致情形,但是對(duì)于每一個(gè)不同的map, 內(nèi)存是如何分配的呢?
這時(shí)候可以通過(guò)/proc/{PID}/smaps來(lái)獲得;