内存管理-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 2024-08-31 11:43 Hello-World3 阅读(120) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2022-08-31 调度器38—cpumask