vmstat -a 命令能看到 active memory 和 inactive memory,但是它們是什麼意思呢?
$ vmstat-a
procs -----------memory-------------swap-------io-----system--------cpu-----
r b swpd free inact active si so bi bo in cs us sy id wa st
1013809631956013724081757848002323109900
它們的含義在 manpage 中只給了簡單的說明,並未詳細解釋:
inact: the amount of inactive memory. (-a option)
active: the amount of active memory. (-a option)
在此我們試圖准確理解它的含義。通過閱讀 vmstat 的源代碼 (vmstat.c 和 proc/sysinfo.c)得知,vmstat 命令是直接從 /proc/meminfo
中獲取的數據:
$ grep-i act /proc/meminfo
Active:1767928 kB
Inactive:1373760 kB
而/proc/meminfo
的數據是在以下內核函數中生成的:
fs/proc/meminfo.c:
==================
0023staticint meminfo_proc_show(struct seq_file *m,void*v)
0024{
...
0032unsignedlong pages[NR_LRU_LISTS];
...
0051for(lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
0052 pages[lru]= global_page_state(NR_LRU_BASE + lru);
...
0095"Active: %8lu kB\n"
0096"Inactive: %8lu kB\n"
0097"Active(anon): %8lu kB\n"
0098"Inactive(anon): %8lu kB\n"
0099"Active(file): %8lu kB\n"
0100"Inactive(file): %8lu kB\n"
...
0148 K(pages[LRU_ACTIVE_ANON]+ pages[LRU_ACTIVE_FILE]),
0149 K(pages[LRU_INACTIVE_ANON]+ pages[LRU_INACTIVE_FILE]),
0150 K(pages[LRU_ACTIVE_ANON]),
0151 K(pages[LRU_INACTIVE_ANON]),
0152 K(pages[LRU_ACTIVE_FILE]),
0153 K(pages[LRU_INACTIVE_FILE]),
這段代碼的意思是統計所有的 LRU list,其中 Active Memory 等於 ACTIVE_ANON 與 ACTIVE_FILE 之和,Inactive Memory 等於 INACTIVE_ANON 與 INACTIVE_FILE 之和。
LRU list 是 Linux 內核的內存頁面回收算法(Page Frame Reclaiming Algorithm)所使用的數據結構,LRU 是 Least Recently Used 的縮寫詞。這個算法的核心思想是:回收的頁面應該是最近使用得最少的。
為了實現這個目標,最理想的情況是每個頁面都有一個年齡項,用於記錄最近一次訪問頁面的時間,可惜 x86 CPU 硬件並不支持這個特性,x86 CPU 只能做到在訪問頁面時設置一個標志位 Access Bit,無法記錄時間。
所以 Linux 內核使用了一個折衷的方法:它采用了 LRU list 列表,把剛訪問過的頁面放在列首,越接近列尾的就是越長時間未訪問過的頁面,這樣,雖然不能記錄訪問時間,但利用頁面在 LRU list 中的相對位置也可以輕松找到年齡最長的頁面。
Linux 內核設計了兩種 LRU list: active list 和 inactive list, 剛訪問過的頁面放進 active list,長時間未訪問過的頁面放進 inactive list,這樣從 inactive list 回收頁面就變得簡單了。內核線程 kswapd 會周期性地把 active list 中符合條件的頁面移到 inactive list 中,這項轉移工作是由 refill_inactive_zone()
完成的。這段代碼的意思是統計所有的 LRU list,其中Active Memory 等於 ACTIVE_ANON 與 ACTIVE_FILE 之和,Inactive Memory 等於 INACTIVE_ANON 與 INACTIVE_FILE 之和。
LRU list 示意圖
LRU_list
vmstat 看到的 active/inactive memory 就分別是 active list 和 inactive list 中的內存大小。如果 inactive list 很大,表明在必要時可以回收的頁面很多;而如果 inactive list 很小,說明可以回收的頁面不多。
Active/inactive memory 是針對用戶進程所占用的內存而言的,內核占用的內存(包括 slab)不在其中。
至於在源代碼中看到的 ACTIVE_ANON 和 ACTIVE_FILE,分別表示 anonymous pages 和 mapped pages。用戶進程的內存頁分為兩種:與文件關聯的內存(比如程序文件、數據文件所對應的內存頁)和與文件無關的內存(比如進程的堆棧,用 malloc 申請的內存),前者稱為 file pages 或 mapped pages,後者稱為 anonymous pages。file pages 在發生換頁(page-in 或 page-out)時,是從它對應的文件讀入或寫出;anonymous pages 在發生換頁時,是對交換區進行讀/寫操作。