测试环境centos7
,内核版本4.20
内核使用cgroup
对进程进行分组,并限制进程资源和对进程进行跟踪。内核通过名为cgroupfs
类型的虚拟文件系统来提供cgroup
功能接口。cgroup
有如下2
个概念:
subsystem
:用于控制cgroup
中的进程行为的内核组件,可以在/proc/cgroups
查看所有支持的subsystem
,subsystem
也别称为resource controller
;第二列为croup id
;第三列为cgroup
中进程数目。
# cat /proc/cgroups
#subsys_name hierarchy num_cgroups enabled
cpuset 8 6 1
cpu 7 105 1
cpuacct 7 105 1
blkio 5 105 1
memory 3 327 1
devices 6 106 1
freezer 4 6 1
net_cls 2 6 1
perf_event 11 6 1
net_prio 2 6 1
hugetlb 9 6 1
pids 12 106 1
rdma 10 1 1
hierarchy
:由cgroup
组成的层级树,每个hierarchy
都对应一个cgroup
虚拟文件系统,每个hierarchy
都有系统上的所有task
,此外低level
的hierarchy
不能超过高level
设定的资源上限
系统默认会挂载cgroup
,路径为/sys/fs/cgroup
,查看当前系统挂载的cgroup
,可以看到在默认路径下挂载了所有的子系统。
后续可以直接使用下述hierarchy
作为父hierarchy
。
进程的cgroup
可以在/proc/$pid/cgroup
文件中查看。
# mount|grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,seclabel,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,rdma)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpu,cpuacct)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_cls,net_prio)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
cgroup
有如下4
个规则:
- 一个
hierarchy
可以有一个或多个subsystem
,这个从/sys/fs/cgroup
中可以看出来cpu
和cpuacct
可以同属于一个hierarchy
,而memory
则仅属于一个hierarchy
; - 一个
subsystem
不能挂载到一个已经挂载了不同subsystem
的hierarchy
上(下面讲); - 一个
task
不能同时存在于同一个hierarchy
下的两个cgoup
中,但可以存在于不同类型的hierarchy
中;如下例中,在hierarchy memory
中创建2
个cgroup mem1
和mem2
,可以看到将当前bash
进程写入到mem2/tasks
之后,mem1/tasks
中的内容就会被清空。注:删除cgroup
之前需要退出所有attach
到该cgroup
的进程,如下面的进程为bash
,exit
退出即可
[root@ memory]# echo $$
9439
[root@ memory]# echo $$ > mem1/tasks
[root@ memory]# cat mem1/tasks
9439
9680
[root@ memory]# echo $$ > mem2/tasks
[root@ memory]# cat mem2/tasks
9439
9693
[root@ memory]# cat mem1/tasks
[root@ memory]#
相同类型subsystem
的hierarchy
为同一个hierarchy
,如下例中创建一个包含memory subsystem
的hierarchy
,它与/sys/fs/cgroup
下面的memory
是一致的,在cgrp1
中创建一个名为mem1
的cgroup
。在/sys/fs/cgroup/memory
下可以看到新创建的mem1
[root@ cgroup]# mount -t cgroup -o memory mem cgrp1/
[root@ cgroup]# cd cgrp1/
[root@ cgrp1]# mkdir mem1
子进程会继承父进程的hierarchy
,但可以将子进程调整到其他cgroup
。下例中可以看到子进程同样受到父进程hierarchy
的限制
[root@ mem1]# echo $$
10928
[root@ mem1]# echo $$>tasks
[root@ mem1]# cat /proc/10928/cgroup
11:devices:/user.slice
10:perf_event:/
9:pids:/user.slice
8:freezer:/
7:cpuacct,cpu:/
6:hugetlb:/
5:memory:/mem1
4:cpuset:/
3:net_prio,net_cls:/
2:blkio:/
1:name=systemd:/user.slice/user-1000.slice/session-1.scope
[root@ mem1]# bash #创建一个子进程
[root@ mem1]# echo $$
11402
[root@ mem1]# cat /proc/11402/cgroup
11:devices:/user.slice
10:perf_event:/
9:pids:/user.slice
8:freezer:/
7:cpuacct,cpu:/
6:hugetlb:/
5:memory:/mem1
4:cpuset:/
3:net_prio,net_cls:/
2:blkio:/
1:name=systemd:/user.slice/user-1000.slice/session-1.scope
从上面可以看到,subsystem
相同的hierarchy
是被重复使用的;当创建一个新的hierarchy
时,如果使用的subsystem
被其他hierarchy
使用,则会返回EBUSY
错误。
如/sys/fs/cgroup
中已经在cpuset
和memory
中单独使用了名为cpuset
和memory
的subsystem
,则重新创建一个包含了它们的hierarchy
会返回错误
[root@ cgroup]# mount -t cgroup -o cpuset,memory mem1 cgrp1/
mount: mem1 is already mounted or /cgroup/cgrp1 busy
可以创建没有subsystem
的hierarchy
,默认包含如下文件:
tasks
:包含了attach
到该cgoup
的pid
。如上述例子中所示,将进程pid
写入到该文件会将进程转移到该cgroup
。(cgroupv2
中移除了该文件,使用cgroup.procs
)cgroup.procs
:包含了线程的group id
。将一个线程的group id
写入该文件,会