新版内核普遍采用 v2 版本的 cgroup
是什么
cgroup 既 Controll group, 是 linux 对外提供的文件接口,用来控制进程资源。
$ mount -t cgroup2
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot,memory_hugetlb_accounting)
使用
新建 group
直接在 /sys/fs/cgroup 下新建目录
$ cd /sys/fs/cgroup/
$ sudo mkdir test
$ ls ./test
cgroup.controllers cpu.stat memory.peak
cgroup.events cpu.stat.local memory.pressure
cgroup.freeze cpu.uclamp.max memory.reclaim
cgroup.kill cpu.uclamp.min memory.stat
cgroup.max.depth cpu.weight memory.swap.current
cgroup.max.descendants cpu.weight.nice memory.swap.events
cgroup.procs
...
重点关注 cgroup.procs 这个文件, 其中的内容(pid)既我们想要控制的进程号。
控制cpu占用率
$ while true; do : ; done &
[1] 50274 # 50274 为对应pid
$ top -b -n 1 -p 50274 | grep "50274" | awk '{print $9}'
99.7 # 此时没有限制,死循环占用100%的cpu
$ echo 50274 | sudo tee cgroup.procs # 直接使用当前shell的进程号, 这样子随后开启的子进程也会受到控制
$ echo 2000 10000 | sudo tee cpu.max # 10000 微秒内 `$$` 进程只能占用 2000 微秒
$ top -b -n 1 -p 50274 | grep "50274" | awk '{print $9}'
19.9 # 20%
控制内存
测试程序
//filepath: ./test_mem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MB (1024 * 1024)
int main() {
char *p;
int i = 0;
while (1) {
p = (char *)malloc(MB);
memset(p, 0, MB);
printf("%d MB allocated\n", ++i);
sleep(1);
}
return 0;
}
gcc ./test_mem.c -o test_mem
test_mem 每隔一秒就申请1 MB 内存并填充(一定要使用 memset 填充,否则会写入虚拟内存,不计入物理内存/交换空间)
$ echo $$ | sudo tee cgroup.procs # 将当前shell的pid传入,shell的子进程(test_mem)也会受限制
$ echo $(( 5 * 1024 * 1024 )) | sudo tee memory.max
$ echo 0 | sudo tee memory.swap.max # 禁用 swap
$ ./test_mem
1 MB allocated
2 MB allocated
...
10 MB allocated
(shell exit)