天天看點

如何通過閱讀源代碼了解 vmstat 中的名額如何通過閱讀源代碼了解 vmstat 中的名額

如何通過閱讀源代碼了解 vmstat 中的名額如何通過閱讀源代碼了解 vmstat 中的名額

vmstat -a 指令能看到 active memory 和 inactive memory,但是它們是什麼意思呢?

<code>$ vmstat -a</code>

<code>procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----</code>

<code>r b swpd free inact active si so bi bo in cs us sy id wa st</code>

<code>1 0 138096 319560 1372408 1757848 0 0 2 3 2 3 1 0 99 0 0</code>

它們的含義在 manpage 中隻給了簡單的說明,并未詳細解釋:

inact: the amount of inactive memory. (-a option) active: the amount of active memory. (-a option)

在此我們試圖準确了解它的含義。通過閱讀 vmstat 的源代碼 (vmstat.c 和 proc/sysinfo.c)得知,vmstat 指令是直接從 <code>/proc/meminfo</code> 中擷取的資料:

<code>$ grep -i act /proc/meminfo</code>

<code>active: 1767928 kb</code>

<code>inactive: 1373760 kb</code>

而<code>/proc/meminfo</code> 的資料是在以下核心函數中生成的:

<code>fs/proc/meminfo.c:</code>

<code>==================</code>

<code>0023 static int meminfo_proc_show(struct seq_file *m, void *v)</code>

<code>0024 {</code>

<code>...</code>

<code></code>

<code>0032 unsigned long pages[nr_lru_lists];</code>

<code>0051 for (lru = lru_base; lru &lt; nr_lru_lists; lru++)</code>

<code>0052 pages[lru] = global_page_state(nr_lru_base + lru);</code>

<code>0095 "active: %8lu kb\n"</code>

<code>0096 "inactive: %8lu kb\n"</code>

<code>0097 "active(anon): %8lu kb\n"</code>

<code>0098 "inactive(anon): %8lu kb\n"</code>

<code>0099 "active(file): %8lu kb\n"</code>

<code>0100 "inactive(file): %8lu kb\n"</code>

<code>0148 k(pages[lru_active_anon] + pages[lru_active_file]),</code>

<code>0149 k(pages[lru_inactive_anon] + pages[lru_inactive_file]),</code>

<code>0150 k(pages[lru_active_anon]),</code>

<code>0151 k(pages[lru_inactive_anon]),</code>

<code>0152 k(pages[lru_active_file]),</code>

<code>0153 k(pages[lru_inactive_file]),</code>

這段代碼的意思是統計所有的 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 中,這項轉移工作是由 <code>refill_inactive_zone()</code> 完成的。這段代碼的意思是統計所有的 lru list,其中active memory 等于 active_anon 與 active_file 之和,inactive memory 等于 inactive_anon 與 inactive_file 之和。

如何通過閱讀源代碼了解 vmstat 中的名額如何通過閱讀源代碼了解 vmstat 中的名額

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 在發生換頁時,是對交換區進行讀/寫操作。

本文來自雲栖社群合作夥伴“linux中國”

原文釋出時間為:2013-04-02.

繼續閱讀