Linux 内核源码分析-理解 cgroup 内存资源控制
准备
内核版本: 5.0
cgroup
全称Control Groups,顾名思义就是把进程放到一个组里面统一加以控制,cgroup
可以限制进程的各种资源,包括用来控制一组进程的内存使用量,cgroup
把各种资源控制器成为子系统,内存控制即为内存子系统.
使用方法
cgroup
目前现存两个版本,我们仅讨论cgroup v1
的使用方法.
Centos安装cgroup:
1
sudo yum -y install libcgroup-tools
在目录`/sys/fs/cgroup”下挂在tmpfs文件系统
1
mount -t tmpfs none /sys/fs/cgroup
在目录
/sys/fs/cgroup
下创建目录memory
1
mkdir /sys/fs/cgroup/memory
在目录
sys/fs/cgroup/memory
下挂载cgroup文件系统, 把内存资源控制器关联到控制组1
mount -t cgroup -o memory none /sys/fs/cgroup/memory
创建新的控制组
1
mkdir /sys/fs/cgroup/memory/test_memory
设置控制组的内存使用限制
2G
:1
sudo echo 2147483648 > /sys/fs/cgroup/memory/test_memory/memory.limit_in_bytes
将线程组加入控制组:
1
sudo echo <pid> > /sys/fs/cgroup/memory/test_memory/cgroup.procs
或者启动进程附带控制组:
1
cgexec -g memory:test_memory ./a.out
cgroup内存子系统
内存资源控制器mem_cgroup
cgroup
的内存资源控制器限制每一个控制组的Page Cache
和RSS
物理内存.
1 | /* |
结构体page_counter
是页计数器,单位为Page:
1 | struct page_counter { |
理解cgroup内存记账
当为内存控制组中的进程分配物理内存时,会记录内存使用量, 内存记账简单的理解为记录控制组的内存使用量, 以下是记录的时间点:
- 第一次访问匿名页时分配物理页.
- 访问文件时分配物理页(Page Cache) .
- 执行COW(写时复制)时,分配物理页.
- 从交换区换入页.
我们仅分析4类中较为常见的访问文件分配物理页的内存记账处理过程:
我们以ext4文件系统为例, 当需要读取文件时,某个Page不在内存中,需要把该Page读取至内存中,即调用address_space
的操作函数ext4_readpage
:
内存计数步骤:
mem_cgroup_try_charge()
用来表示尝试记账, 把内存控制组的内存计数加上指定的数量.如果成功,调用
mem_cgroup_commit_charge()
以提交计数,否则调用mem_cgroup_cancel_charge()
放弃计数.
OOM killer
cgroup的内存控制器是默认开启OOM killer,当进程消耗的内存超过了cgroup的限制,就会调用OOM killer,向指定的进程发送杀死信号SIGKILL
. 假如触发了OOM,关于crgroup内存控制kill的信息,可以通过dmesg
进行查看.
dmesg示例
新建了一个名为test_cgroup
的控制组, 使用进程a.out
申请超过cgroup限制大小的内存:
Q&A
使用cgroup遇到
cgroup change of group failed
问题:注意
/sys/fs/cgroup/test_memory
即控制组的目录权限, 是否与执行进程的文件权限保持一致.即使进程以及完全退出,cgroup的内存控制组目录仍然无法清理?
因为cgroup会限制进程使用Page Cache,而Page Cache的清理不会随着进程的退出而完成,所以当我们使用cgroup限制的进程有文件读写操作从而使用了Page Cache, 会导致cgroup内存控制组目录无法清理,所以正确的做法是清空Page Cache:
echo 3 > /proc/sys/vm/drop_caches
或者echo 3 > /cgroup/memory/test_memory/memory.drop_caches
参考
《Linux内核深度解析》