cgroup

简介

cgroup 能够限制进程的 CPU,memory,IO 等资源的使用比例。

编译

编译 Linux 内核时,使能 CONFIG_MEMCG 选项,打开 cgroup memory 功能。

查看 cgroup 版本

$ stat -fc %T /sys/fs/cgroup/
cgroup2fs
## or
$ mount | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)

对比不同版本的 cgroup

cgroup v1
cgroup v2
备注

memory.usage_in_bytes

memory.current

当前内存使用量

memory.max_usage_in_bytes

memory.peak

最大内存使用量

memory.soft_limit_in_bytes

memory.high

当此 cgroup 内存超过此值,进行内存回收

memory.limit_in_bytes

memory.max

设置最大能够使用的内存大小

memory.force_empty

memory.reclaim

回收内存,v1 全部回收,v2 回收指定内存量

memory.swappiness

memory.reclaim

设置回收 anon:file page 的趋势

memory.memsw.usage_in_bytes

memory.swap.current

当前 swap 使用量

memory.memsw.max_usage_in_bytes

memory.swap.peak

最大 swap 使用量

memory.memsw.limit_in_bytes

memory.swap.max

设置最大能够使用的 swap 使用量

memory.memsw.failcnt

memory.swap.events

swap 失败次数

下面主要介绍 cgroup v2 的源码以及原理。

接口描述

memory.current

memory.peak

memory.min

memory.low

memory.high

memory.max

memory.reclaim

memory.oom.group

memory.events

memory.events.local

memory.stat

memory.numa_stat

memory.swap.current

memory.swap.peak

memory.swap.high

memory.swap.max

memory.swap.events

memory.zswap.current

memory.zswap.max

memory.zswap.writeback

memory.pressure

如何限制 cgroup memory 的内存使用?

当触发 pagefault 申请物理内存时,调用 mem_cgroup_charge() 判断当前进程所属 cgroup 是否有足够的空闲内存。如果有,申请成功。否则,申请失败 OOM。

先调用 consume_stock() 从 memcg_stock 中查找是否有足够的空闲内存,如果有, 申请成功,直接返回。否则,

调用 page_counter_try_charge()memcg->memory 中查找是否有至少 64 页的 空闲内存?

如果有,申请成功。然后调用 refill_stock() 将多申请的内存存储到 memcg_stock 中, 同时如果 cgroup 内存使用量超过 memory.high,调用 mem_cgroup_handle_over_high() 进行内存回收等处理。

如果没有,申请失败,但是有 PF_MEMALLOC 标志,直接调用 page_counter_charge() 无条件申请内存成功,直接返回。

如果没有,申请失败,但是允许阻塞,调用 try_to_free_mem_cgroup_pages() 进行 直接内存回收,如果回收后有足够的空闲内存,再从头开始申请内存。否则,

调用 drain_all_stock() 将 memcg_stock 缓存的所有内存释放到 cgroup 中,并且 再从头开始申请内存。

实在没有办法了,目前 cgroup 中使用的内存量已经达到 memory.max,调用 mem_cgroup_oom() 触发 OOM killer,并且再从头开始申请内存。

Last updated

Was this helpful?