mem cgroup-2-memcg文件节点介绍

基于kernel-6.1.114

一、相关文件节点

1. /dev/memcg

/dev/memcg # ls -l
drwxr-xr-x 2 system system 0 2010-01-01 08:00 apps //子目录
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 cgroup.clone_children //0
--w--w--w- 1 root   root   0 2010-01-01 09:16 cgroup.event_control
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 cgroup.procs //大量
-r--r--r-- 1 root   root   0 2010-01-01 09:16 cgroup.sane_behavior //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.failcnt //0
--w------- 1 root   root   0 2010-01-01 09:16 memory.force_empty
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.failcnt //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.limit_in_bytes //9223372036854771712 = 0x7FFFFFFFFFFFFFF0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.max_usage_in_bytes //0
-r--r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.slabinfo //
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.tcp.failcnt //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.tcp.limit_in_bytes //9223372036854771712
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.tcp.max_usage_in_bytes //0
-r--r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.tcp.usage_in_bytes //0
-r--r--r-- 1 root   root   0 2010-01-01 09:16 memory.kmem.usage_in_bytes //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.limit_in_bytes //9223372036854771712
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.max_usage_in_bytes //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.memsw.failcnt //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.memsw.limit_in_bytes //9223372036854771712
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.memsw.max_usage_in_bytes //0
-r--r--r-- 1 root   root   0 2010-01-01 09:16 memory.memsw.usage_in_bytes //9677598720 ####
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.move_charge_at_immigrate //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.oom_control //oom_kill_disable 0, under_oom 0, oom_kill 0
----r----- 1 root   system 0 2010-01-01 08:00 memory.pressure_level //cat报错"cat: memory.pressure_level: Invalid argument"
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.soft_limit_in_bytes //9223372036854771712
-r--r--r-- 1 root   root   0 2010-01-01 09:16 memory.stat //见下文cat
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.swappiness //100
-r--r--r-- 1 root   root   0 2010-01-01 09:16 memory.usage_in_bytes //7395565568 ####
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 memory.use_hierarchy //1
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 notify_on_release //0
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 release_agent //
dr-xr-x--- 2 system system 0 2010-01-01 08:00 system //子目录
-rw-r--r-- 1 root   root   0 2010-01-01 09:16 tasks //大量

memory.stat 文件内容:

/dev/memcg # cat memory.stat
cache 3447140352
rss 3951267840
rss_huge 0
shmem 35467264
mapped_file 1750802432
dirty 483328
writeback 0
workingset_refault_anon 76330
workingset_refault_file 212187
swap 2282438656
pgpgin 16405153
pgpgout 14612101
pgfault 19587646
pgmajfault 90014
inactive_anon 769310720
active_anon 3207593984
inactive_file 1358106624
active_file 2060623872
unevictable 5656576
hierarchical_memory_limit 9223372036854771712
hierarchical_memsw_limit 9223372036854771712
total_cache 3447140352
total_rss 3951267840
total_rss_huge 0
total_shmem 35467264
total_mapped_file 1750802432
total_dirty 483328
total_writeback 0
total_workingset_refault_anon 76330
total_workingset_refault_file 212187
total_swap 2282438656
total_pgpgin 16405153
total_pgpgout 14612101
total_pgfault 19587646 //和 /proc/vmstat 的 pgfault 一致
total_pgmajfault 90014
total_inactive_anon 769310720
total_active_anon 3207593984
total_inactive_file 1358106624
total_active_file 2060623872
total_unevictable 5656576


2. /dev/memcg/apps 和 /dev/memcg/system

实际 cat 看,apps 目录和 system 目录打印出来的内容都一样,这里以 apps 目录为例:

/dev/memcg # ls apps/ -l
-rw-r--r-- 1 root root 0 2010-01-01 09:24 cgroup.clone_children //0
--w--w--w- 1 root root 0 2010-01-01 09:24 cgroup.event_control
-rw-r--r-- 1 root root 0 2010-01-01 09:24 cgroup.procs //
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.failcnt //0
--w------- 1 root root 0 2010-01-01 09:24 memory.force_empty
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.failcnt //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.limit_in_bytes //9223372036854771712 = 0x7FFFFFFFFFFFFFF0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.max_usage_in_bytes //0
-r--r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.slabinfo //
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.tcp.failcnt //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.tcp.limit_in_bytes //9223372036854771712
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.tcp.max_usage_in_bytes //0
-r--r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.tcp.usage_in_bytes //0
-r--r--r-- 1 root root 0 2010-01-01 09:24 memory.kmem.usage_in_bytes //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.limit_in_bytes //9223372036854771712
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.max_usage_in_bytes //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.memsw.failcnt //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.memsw.limit_in_bytes //9223372036854771712
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.memsw.max_usage_in_bytes //0
-r--r--r-- 1 root root 0 2010-01-01 09:24 memory.memsw.usage_in_bytes //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.move_charge_at_immigrate //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.oom_control //oom_kill_disable 0, under_oom 0, oom_kill 0
---------- 1 root root 0 2010-01-01 09:24 memory.pressure_level //子目录的既不能读,又不能写
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.soft_limit_in_bytes //9223372036854771712
-r--r--r-- 1 root root 0 2010-01-01 09:24 memory.stat //见下文cat
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.swappiness //60
-r--r--r-- 1 root root 0 2010-01-01 09:24 memory.usage_in_bytes //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 memory.use_hierarchy //1
-rw-r--r-- 1 root root 0 2010-01-01 09:24 notify_on_release //0
-rw-r--r-- 1 root root 0 2010-01-01 09:24 tasks //

memory.stat 文件节点内容:

/dev/memcg/apps # cat memory.stat
cache 0
rss 0
rss_huge 0
shmem 0
mapped_file 0
dirty 0
writeback 0
workingset_refault_anon 0
workingset_refault_file 0
swap 0
pgpgin 0
pgpgout 0
pgfault 0
pgmajfault 0
inactive_anon 0
active_anon 0
inactive_file 0
active_file 0
unevictable 0
hierarchical_memory_limit 9223372036854771712
hierarchical_memsw_limit 9223372036854771712
total_cache 0
total_rss 0
total_rss_huge 0
total_shmem 0
total_mapped_file 0
total_dirty 0
total_writeback 0
total_workingset_refault_anon 0
total_workingset_refault_file 0
total_swap 0
total_pgpgin 0
total_pgpgout 0
total_pgfault 0
total_pgmajfault 0
total_inactive_anon 0
total_active_anon 0
total_inactive_file 0
total_active_file 0
total_unevictable 0


二、文件节点介绍

1. 子组的文件节点

1.1 apps

含义:子内存控制组目录,通常放应用进程。作用:在这个目录下再有一套同名 memory.* 文件,代表该子组的独立内存控制状态。

1.2 system

含义:另一个子组,通常放系统服务进程。作用同上,和 apps 隔离统计与限制。


2. 通用控制文件

2.1 cgroup.clone_children

含义:历史兼容开关。在 memcg 上通常没有实际业务价值,更多是旧接口保留。很多系统里可忽略。


2.2 cgroup.event_control

含义:事件订阅入口(写接口)。把 eventfd 和某个“事件源文件”绑定,例如 memory.oom_control、memory.pressure_level。
典型用途:用户态守护进程通过 eventfd 收到 OOM 或压力事件通知。
注意:这是配置接口,本身不直接返回“状态值”。


2.3 cgroup.procs

含义:该 cgroup 中的进程(TGID)列表。读:返回进程号列表。写:写入一个 PID,把该进程(通常线程组整体)迁入当前 cgroup。


2.4 tasks

含义:该 cgroup 中的线程(TID)列表。读:返回线程号列表。写:写入一个 TID,把该线程迁入当前 cgroup。
与 cgroup.procs 区别:procs 偏进程粒度,tasks 偏线程粒度。


2.5 notify_on_release

含义:释放通知开关。写 1:当该 cgroup 变空且被释放时,可触发 release_agent 机制。现代系统较少使用。


2.5 release_agent

含义:release 回调程序路径。只有根组有。配合 notify_on_release 使用,cgroup 释放时由内核触发该程序。
安全敏感,生产环境通常禁用或不用。


2.6 cgroup.sane_behavior

含义:历史“层级行为”兼容标志。只有根组有。现代内核上基本是遗留接口,通常不作为调优项使用。


3. memory 主控制文件

3.1 memory.usage_in_bytes

含义:当前已计费内存使用量(主要是用户内存页相关)。
说明:是动态值,瞬时抖动正常。


3.2 memory.max_usage_in_bytes

含义:历史峰值使用量。写 0:重置峰值计数。


3.3 memory.limit_in_bytes

含义:硬限制(hard limit)。达到后会触发回收,仍无法满足时可能触发 memcg OOM。常见写法:写具体字节数;“无限制”常用非常大值(不同内核表现略有差异)。


3.4 memory.soft_limit_in_bytes

含义:软限制(best effort)。不是硬约束,只在全局内存紧张时作为回收优先级参考。


3.5 memory.failcnt

含义:命中 memory.limit_in_bytes 失败次数累计。写 0:清零。


3.6 memory.stat

含义:详细分项统计。
常见字段:rss、cache、mapped_file、pgfault、pgmajfault、inactive_anon、active_file 等。
用途:定位“谁在吃内存”和回收行为分析。


3.7 memory.swappiness

含义:该 cgroup 的 swap 倾向。常见范围:0 到 100。0 倾向少换出匿名页,100 倾向积极换出匿名页。


3.8 memory.force_empty

含义:强制回收该 cgroup 可回收页面(写触发)。常用于删除 cgroup 前尽量清空占用。注意:不是“绝对清空”,不可回收页、被引用页、pin 住页可能仍在。


3.9 memory.use_hierarchy

含义:是否按层级统计/限制。v1 老内核可配;新一些内核往往固定层级行为,写入可能被忽略或限制。在 Android 旧栈里常见为 1。


3.10 memory.move_charge_at_immigrate

含义:任务迁移时,是否连带迁移历史页面 charge。0:不迁移历史 charge。非 0:按位掩码迁移(不同内核位定义有差异,常见是匿名页/文件页位)。
用途:任务从组 A 移到组 B 后,让账单也跟着迁。


4. memory + swap(memsw)控制

4.1 memory.memsw.usage_in_bytes

含义:当前 memory + swap 合计使用量。


4.2 memory.memsw.max_usage_in_bytes

含义:history 峰值(memory + swap)。写 0:清零峰值。


4.3 memory.memsw.limit_in_bytes

含义:memory + swap 总硬限制。如果设置了 memory.limit_in_bytes 和 memsw.limit_in_bytes,两者共同生效。


4.4 memory.memsw.failcnt

含义:命中 memsw 限制失败计数。写 0:清零。

注意: memsw 依赖内核配置和启动参数(如 swapaccount)。某些 Android 设备虽然文件存在,但 swap 实际没开或策略受限,效果会打折。


5. kmem(内核内存)控制

5.1 memory.kmem.usage_in_bytes

含义:该 cgroup 的内核内存计费使用量。


5.2 memory.kmem.max_usage_in_bytes

含义:kmem 峰值。写 0 清零峰值。


5.3 memory.kmem.limit_in_bytes

含义:kmem 硬限制。老特性,现代内核很多场景已弱化或被统一内存计费替代。


5.4 memory.kmem.failcnt

含义:命中 kmem limit 的失败计数。写 0 清零。


5.5 memory.kmem.slabinfo

含义:按 slab 缓存维度的 memcg 统计。用于排查 slab 泄漏或某类内核对象异常膨胀。
注意:读取开销可能较大。


6. kmem.tcp(TCP 内核缓冲)控制

6.1 memory.kmem.tcp.usage_in_bytes

含义:TCP 相关内核内存使用量(skb、socket buffer 等)。


6.2 memory.kmem.tcp.max_usage_in_bytes

含义:TCP kmem 峰值。写 0 清零峰值。


6.3 memory.kmem.tcp.limit_in_bytes

含义:TCP kmem 硬限制。


6.4 memory.kmem.tcp.failcnt

含义:命中 TCP kmem limit 失败次数。写 0 清零。


7. OOM与压力通知

7.1 memory.oom_control

含义:memcg OOM 控制与状态。
常见字段:oom_kill_disable、under_oom、oom_kill。
用途:查看该组是否发生过/正在发生 OOM,以及是否禁用 OOM kill。还可配合 cgroup.event_control 做事件通知。


7.2 memory.pressure_level

含义:内存压力事件源(低/中/高压力)。常见不是直接读文本,而是配合 cgroup.event_control + eventfd 订阅事件。你看到权限是 "----r-----" 且属组 system,说明通常只给特定系统服务读取。只有根组的有读权限,但是 cat 依然报 "Invalid argument"。


三、实战上最常用文件

调限制:memory.limit_in_bytes、memory.soft_limit_in_bytes、memory.swappiness。

看当前和峰值:memory.usage_in_bytes、memory.max_usage_in_bytes。

看是否撞线:memory.failcnt、memory.oom_control。

深挖原因:memory.stat、memory.kmem.slabinfo。

迁移任务:cgroup.procs 或 tasks。

 

posted on 2026-07-31 16:59  Hello-World3  阅读(8)  评论(0)    收藏  举报

导航