内存管理-31-系统内存统计-4-/proc/vmstat

基于msm-5.4

一、打印内容

1. 打印格式

复制代码
# cat /proc/vmstat
/* 1. 打印全局数组 vm_zone_stat[] 的值,enum zone_stat_item 描述各条目 */
nr_free_pages 617775
nr_zone_inactive_anon 16518
nr_zone_active_anon 979541
nr_zone_inactive_file 698879
nr_zone_active_file 172233
nr_zone_unevictable 799
nr_zone_write_pending 23
nr_mlock 799
nr_page_table_pages 30669
nr_kernel_stack 62368
nr_shadow_call_stack_bytes 15966208
nr_bounce 0
nr_zspages 3271
nr_free_cma 0
/* 2. 打印全局数组 vm_node_stat[] 的值,enum node_stat_item 描述各条目 */
nr_inactive_anon 16518
nr_active_anon 979541
nr_inactive_file 698879
nr_active_file 172233
nr_unevictable 799
nr_slab_reclaimable 35540
nr_slab_unreclaimable 56547
nr_isolated_anon 0
nr_isolated_file 0
workingset_nodes 10
workingset_refault 6019
workingset_activate 6019
workingset_restore 0
workingset_nodereclaim 0
nr_anon_pages 982470
nr_mapped 537561
nr_file_pages 899517
nr_dirty 23
nr_writeback 0
nr_writeback_temp 0
nr_shmem 13782
nr_shmem_hugepages 0
nr_shmem_pmdmapped 0
nr_file_hugepages 0
nr_file_pmdmapped 0
nr_anon_transparent_hugepages 0
nr_unstable 0
nr_vmscan_write 18979
nr_vmscan_immediate_reclaim 8
nr_dirtied 77330
nr_written 93219
nr_kernel_misc_reclaimable 40568
nr_unreclaimable_pages 156794
/* 3. 收集全局变量 struct wb_domain global_wb_domain 的成员,分别是 thresh 和 bg_thresh */
nr_dirty_threshold 293883
nr_dirty_background_threshold 73201
/* 4. 以每个cpu为单位,收集 per_cpu(vm_event_states, cpu) 的和,各元素由 enum vm_event_item 描述 */
pgpgin 2174532
pgpgout 297144
pswpin 9200
pswpout 18979
pgalloc_normal 20942336
pgalloc_movable 0
allocstall_normal 0
allocstall_movable 0
pgskip_normal 0
pgskip_movable 0
pgfree 21569479
pgactivate 408312
pgdeactivate 49
pglazyfree 0
pgfault 5143535
pgmajfault 17558
pglazyfreed 0
pgrefill 0
pgsteal_kswapd 0
pgsteal_direct 0
pgscan_kswapd 0
pgscan_direct 0
pgscan_direct_throttle 0
pginodesteal 0
slabs_scanned 0
kswapd_inodesteal 0
kswapd_low_wmark_hit_quickly 0
kswapd_high_wmark_hit_quickly 0
pageoutrun 0
pgrotated 1613
drop_pagecache 0
drop_slab 0
oom_kill 0
pgmigrate_success 806
pgmigrate_fail 0
compact_migrate_scanned 0
compact_free_scanned 0
compact_isolated 8531
compact_stall 0
compact_fail 0
compact_success 0
compact_daemon_wake 0
compact_daemon_migrate_scanned 0
compact_daemon_free_scanned 0
unevictable_pgs_culled 802
unevictable_pgs_scanned 0
unevictable_pgs_rescued 3
unevictable_pgs_mlocked 803
unevictable_pgs_munlocked 4
unevictable_pgs_cleared 0
unevictable_pgs_stranded 0
thp_fault_alloc 0
thp_fault_fallback 0
thp_collapse_alloc 0
thp_collapse_alloc_failed 0
thp_file_alloc 0
thp_file_mapped 0
thp_split_page 0
thp_split_page_failed 0
thp_deferred_split_page 0
thp_split_pmd 0
thp_zero_page_alloc 0
thp_zero_page_alloc_failed 0
thp_swpout 0
thp_swpout_fallback 0
swap_ra 57
swap_ra_hit 39
复制代码

打印的各个条目的字符串来自 vmstat_text[], 各条目的值分别来自全局数组 vm_zone_stat[]、全局数组 vm_node_stat[]、全局变量 struct wb_domain global_wb_domain 的成员、以每个cpu为单位收集 per_cpu(vm_event_states, cpu) 的和。


2. 成员说明

nr_free_pages: 系统当前可用的空闲页数量。

nr_zone_inactive_anon: 所有zone统计的非活跃的匿名页数之和。

nr_zone_active_anon: 所有zone统计的活跃的匿名页数之和。

nr_zone_inactive_file: 所有zone统计的非活跃的文件页数之和。

nr_zone_active_file: 所有zone统计的非活跃的文件页数之和。

nr_zone_unevictable: 所有zone统计的不可释放的页数之和。

nr_zone_write_pending: 脏页、回写页和不稳定页的数量。

nr_mlock: mlock的页数。

nr_page_table_pages: 分配到页表的页数。

nr_kernel_stack: 分配给内核堆栈的内存页数。

nr_shadow_call_stack_bytes:

nr_bounce: dma缓冲取页数量。

nr_zspages: zsmalloc 分配器分配的页数量。

nr_free_cma: 可用CMA页面的数量。

nr_inactive_anon: 所有node统计的非活跃的匿名页数之和.

nr_active_anon: 所有node统计的活跃的匿名页数之和.

nr_inactive_file: 所有node统计的非活跃的文件页数之和.

nr_active_file: 所有node统计的非活跃的文件页数之和.

nr_unevictable: 所有node统计的不可释放的页数之和.

nr_slab_reclaimable: 可回收 slab 缓存对象占用的页数。已经分配出去的reclaimable slab object的内存大小.

nr_slab_unreclaimable: 不可回收 slab 缓存对象占用的页数。已经分配出去的unreclaimable slab object的内存大小.

nr_isolated_anon: 来自匿名 lru 的临时隔离页面.

nr_isolated_file: 来自文件 lru 的临时隔离页面.

workingset_nodes: TODO

workingset_refault: 先前被驱逐的页面的重新fault缺页异常的次数。

workingset_activate: 立即激活的重新fault缺页异常页面的数量。

workingset_restore: 在回收之前被检测为活动工作集的已恢复页面的数量。

workingset_nodereclaim: 影子节点被回收的次数.

nr_anon_pages: 匿名页的页数。

nr_mapped: 映射到文件使用的总页数。

nr_file_pages: 表示所有缓存页的总和,包含了cache和buffers, total_swapcache_pages.

nr_dirty: 此刻正在等待刷新到磁盘上的脏页数目。

nr_writeback: 回写页数。目前正在进行 I/O 写入操作的脏页数目。

nr_writeback_temp: Writeback using temporary buffers(主要是fuse fs在writepage的时候申请的页数量).

nr_shmem: shmem 和 tmpfs 使用的页面.

nr_shmem_hugepages: transparent shmem huge pages.

nr_shmem_pmdmapped: shmem 大页面当前已进行大页映射的页数。

nr_file_hugepages: 文件大页数量.

nr_file_pmdmapped: 当前大页映射的文件大页的数量。

nr_anon_transparent_hugepages: 匿名thp页的数量(以大页为单位,即不以4k为单位记)

nr_unstable: 不稳定页面数。

nr_vmscan_write: 在 LRU 扫描期间写回脏页。

nr_vmscan_immediate_reclaim: 见函数 shrink_page_list(),此处是把页置上reclaim标志然后就退出。

nr_dirtied: 自启动以来的页面污染数量。

nr_written: 自启动以来的页面写入。

nr_kernel_misc_reclaimable: 可回收的非slab的内核内存页。

nr_unreclaimable_pages:

nr_dirty_threshold: 后台回写阈值,见 global_dirty_limits().

nr_dirty_background_threshold: 脏页限制门限,见 global_dirty_limits().

pgpgin: 读入的页数,见 submit_bio().

pgpgout: 写出的页数,见 submit_bio().

pswpin: 读入的交换分区页数。

pswpout: 换出的交换分区页数。

pgalloc_normal: 从zone normal分配的页数。

pgalloc_movable: 从zone movable分配的页数。

allocstall_normal: 申请zone normal内存时触发直接内存回收次数。####

allocstall_movable: 申请zone movable内存时触发直接内存回收次数。

pgskip_normal: 在 isolate_lru_pages() 中由于和需求的zone不符,跳过的zone normal的page数量.

pgskip_movable: 在 isolate_lru_pages() 中由于和需求的zone不符,跳过的zone movable的page数量.

pgfree: 释放的页数.

pgactivate: 放到active链表上的页数.

pgdeactivate: 放到inactive链表上的页数.

pglazyfree: 内存压力下推迟释放的页面数量.

pgfault: 缺页异常次数,即由于缺少所需页面而导致的缺页中断次数。

pgmajfault: 需通过读磁盘解决的缺页数量。

pglazyfreed: 在内存回收从lru成功隔离符合回收条件的pages后,如果是匿名映射的page并且没有PG_swapbacked的falg,增加一次该事件的计数,说明后续是可以直接释放该page,无需swap out的。可以通过madvise(MADV_FREE)设置某匿名vma内映射的pages,如果系统内存紧张决定回收pages,不用交换,后续直接释放。

pgrefill: 从 active/inactive 链表中扫描的页数量.

pgsteal_kswapd: kswapd从inactive链表中回收的页数.

pgsteal_direct: 直接内存回收从inactive链表中回收的页数.

pgscan_kswapd: 从inactive链表中扫描的页数量.

pgscan_direct: 直接内存回收从inactive链表中扫描的页数量.

pgscan_direct_throttle: 限制直接内存回收的次数.

pginodesteal: 从启动到现在通过释放inode节点回收的页面数.

slabs_scanned: do_shrink_slab中尝试释放的object数量.

kswapd_inodesteal: 从启动到现在由kswapd通过释放inode节点回收的页面数.

kswapd_low_wmark_hit_quickly: kswapd尝试进行0.1s的睡眠,结果还没经过0.1s就因为内存触发了low水线导致被唤醒的次数.

kswapd_high_wmark_hit_quickly: 100 毫秒后,可用页面数量降至高水位线以下。这导致 kswapd 继续运行的次数。

pageoutrun: 当系统尝试释放足够的内存时未能成功的情况计数。也有文档说是kswapd主循环运行次数。

pgrotated: 将页面放置到链表尾部(轮转)的页数.

drop_pagecache: 通过 /proc/sys/vm/drop_caches 接口释放pagecache的次数.

drop_slab: 通过 /proc/sys/vm/drop_caches 接口释放slab内存的次数.

oom_kill: 杀进程次数.

pgmigrate_success: migrate_pages()中成功迁移的页数量.

pgmigrate_fail: migrate_pages()中迁移失败的页数量.

compact_migrate_scanned: compact_zone()中扫描的迁移页数.

compact_free_scanned: compact_zone()中扫描的free页数.

compact_isolated: 内存规整时隔离的页数.

compact_stall: 每次进程停止下来运行内存压缩以便释放一个大页面块供使用时,此成员都会增加。

compact_fail: 如果系统尝试压缩内存但失败,则此成员会增加1.

compact_success: 如果系统压缩内存并释放了大页面块以供使用,则此成员会增加。

compact_daemon_wake: 表示 kcompactd 被唤醒的次数.

compact_daemon_migrate_scanned: 表示 kcompactd 已扫描的迁移页面数.

compact_daemon_free_scanned: 表示 kcompactd 已扫描的空闲页面数.

unevictable_pgs_culled: __pagevec_lru_add_fn()中,若页之前是不可移动的,现在将其变为可移动的的次数.

unevictable_pgs_scanned: check_move_unevictable_pages()中扫描页的个数.

unevictable_pgs_rescued: __pagevec_lru_add_fn()中,若页之前是可移动的,现在将其变为不可移动的的次数.

unevictable_pgs_mlocked: 将页设置为 mlock 且移入 unevictable list 的次数.

unevictable_pgs_munlocked: 将页移除 mlock 且移入合适的 lru list 的次数.

unevictable_pgs_cleared: clear_page_mlock()中将页移除 mlock 标记的次数。

unevictable_pgs_stranded: 解锁后无法隔离(unable to isolate on unlock)的次数。

thp_fault_alloc: 每当处理缺页异常时,一个大页面被成功分配,此成员就会增加。这适用于第一次出现缺页异常和COW错误。

thp_fault_fallback: 如果缺页异常分配一个大页失败,则此成员增加,而回退使用小页面。

thp_collapse_alloc: 当它发现一个范围的页面坍缩成一个大页,并有成功分配一个新的巨大页来存储数据,则此成员会被 khugepaged 增加。

thp_collapse_alloc_failed: 当它发现一个范围的页面应该被坍缩成一个大页, 但是分配大页失败,此成员会被 khugepaged 增加。

thp_file_alloc: 在文件大页成功分配时递增。

thp_file_mapped: 每映射到一个文件大页到用户地址空间,此成员就会增加一次。

thp_split_page: THP成功拆分成普通page的次数,swap out或者madvise系统调用修改vma属性,都会触发该事件。

thp_split_page_failed: THP拆分成普通page失败的次数。如果页面被人pin住了,就会发生这种情况。

thp_deferred_split_page: 延迟拆分THP成普通page的个数。在只断开THP部分子页的映射时,并不会立刻拆分,当内存紧张时才会调用shrinker去拆分THP成普通page,并释放空闲的子页。当大页被放到分裂队列时,此成员被增加。当一个巨大的页面部分被unmap且分裂它将释放一些内存就会发生这种情况。分裂队列上的页将在内存压力下分裂。

thp_split_pmd: 调整vma的时候(合并或者分离),若新的vma的起始和结束地址未对齐,并且vma中有THP映射,会记录拆分PMD页表为PTE的次数。每当pmd分裂成pte表时,此成员就会递增。例如,当应用程序调用 mprotect() 或 unmap() 在大页面的一部分。它不会分割大页面,只是页表条目。

thp_zero_page_alloc: 缺页时,若地址所在vma是只读,会默认分配THP zero page,并且内核只保存一份零页,在其他只读vma缺页时,也会共享这个零页,不再重新分配。该事件只记录从伙伴系统成功分配零页的次数。

thp_zero_page_alloc_failed: 该事件只记录从伙伴系统未成功分配零页的次数。

thp_swpout: 指的是pswpout事件中是thp换出事件的计数.

thp_swpout_fallback: 在 swap out 之前,会先将 page 挂到 swap cache,如果添加到 swap cache 失败,会将 thp 拆分的正常的 page,然后再次尝试将 page 添加到 swap cache,同时增加一次计数。

swap_ra: swap in 时未命中swap cache,然后从swap空间预读的次数。

swap_ra_hit: swap in 的时候会先从 swap cache 找 page,命中的次数。


二、实现

复制代码
void __init init_mm_internals(void) //vmstat.c
{
    proc_create_seq("vmstat", 0444, NULL, &vmstat_op);
}

static void *vmstat_start(struct seq_file *m, loff_t *pos) //vmstat.c
{
    unsigned long *v;
    int i, stat_items_size;

    /* 表示要分配内存的大小,这些条目的信息都会在这里进行打印 */
    stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) +
              NR_VM_NUMA_STAT_ITEMS * sizeof(unsigned long) +
              NR_VM_NODE_STAT_ITEMS * sizeof(unsigned long) +
              NR_VM_WRITEBACK_STAT_ITEMS * sizeof(unsigned long);

#ifdef CONFIG_VM_EVENT_COUNTERS
    stat_items_size += sizeof(struct vm_event_state);
#endif

    m->private = v = kmalloc(stat_items_size, GFP_KERNEL);

    /* 1. 收集全局数组 vm_zone_stat[] 的信息 */
    for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) //enum zone_stat_item条目的个数
        v[i] = global_zone_page_state(i); //v[i] = vm_zone_stat[i]
    v += NR_VM_ZONE_STAT_ITEMS;

    /* 2. 收集全局数组 vm_node_stat[] 的信息 */
    for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) //enum node_stat_item 条目的个数
        v[i] = global_node_page_state(i); //v[i] = vm_node_stat[i];
    v += NR_VM_NODE_STAT_ITEMS;

    /* 3. 收集全局变量 struct wb_domain global_wb_domain 的成员。
     * v[0]=dirty_throttle_control.thresh; v[1]=dirty_throttle_control.bg_thresh;
     */
    global_dirty_limits(v + NR_DIRTY_BG_THRESHOLD, v + NR_DIRTY_THRESHOLD);
    v += NR_VM_WRITEBACK_STAT_ITEMS;

#ifdef CONFIG_VM_EVENT_COUNTERS
    /* 4. 以每个cpu为单位收集 per_cpu(vm_event_states, cpu) 的和 */
    all_vm_events(v); //enum vm_event_item 有 NR_VM_EVENT_ITEMS 个条目
    v[PGPGIN] /= 2;     /* sectors -> kbytes */
    v[PGPGOUT] /= 2;
#endif
    return (unsigned long *)m->private + *pos;
}
复制代码

 

参考:
Documentation/admin-guide/mm/transhuge.rst
/proc/vmstat输出含义: https://blog.csdn.net/kaka__55/article/details/125236633

 

posted on   Hello-World3  阅读(120)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2022-08-31 调度器38—cpumask

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示