天天看点

如何通过阅读源代码了解 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.

继续阅读