cgroup的简单使用
cgroup(control group)是由linux内核提供的功能,可以对一组进程使用的资源进行监控、管理和限制。
工作机制
cgroup的工作机制有四部分组成:任务(task),控制组(cgroup),子系统(subsystem)和层级(hierarchy)。
任务(
task)cgroup中的任务实际上就是指系统中的进程。控制组(
cgroup)控制组是层级(
hierarchy)树中的某一个节点,其中包含了一组任务和某个subsystem的相关控制项。子系统(
subsystem)一个子系统实际上就是一个提供了对某种资源控制功能的内核模块。
cgroup支持多种subsystem,每一种subsystem可以针对某一种资源进行控制管理,如memory、block IO等等。层级(
hierarchy)hierarchy是以目录树的形式组织起来的control groups,一个层级可以与0个或者多个subsystem关联,关联后即可对hierarchy中某一层级的cgroup通过subsystem进行资源控制。

如上图所示,cgroup中各个组成部分之间的关系:
- 一个子系统最多只能被添加到一个层级中
- 一个层级可以关联多个子系统,也可以不关联子系统
- 一个任务可以被添加到多个控制组中,但控制组所属的层级必须不同,即任务在层级中只能属于一个
cgroup - 系统中进程创建子进程时,子进程会被自动添加到父进程所在的
cgroup中。 - 创建新的
hierarchy时,会将当前系统中所有进程添加到其root cgroup中。
内核编译选项
前面提到subsystem是内核模块,开启这些内核模块需要在编译内核时打开对应的选项
| 子系统 | 内核选项 | 依赖项 | 内核版本 |
|---|---|---|---|
cpu |
CONFIG_CGROUP_SCHED |
2.6.24 |
|
cpuacct |
CONFIG_CGROUP_CPUACCT |
2.6.24 |
|
cpuset |
CONFIG_CPUSETS |
2.6.24 |
|
memory |
CONFIG_MEMCG |
RESOURCE_COUNTERS |
2.6.25 |
devices |
CONFIG_CGROUP_DEVICE |
2.6.26 |
|
freezer |
CONFIG_CGROUP_FREEZER |
2.6.28 |
|
net_cls |
CONFIG_CGROUP_NET_CLASSID |
2.6.29 |
|
blkio |
CONFIG_BLK_CGROUP |
2.6.33 |
|
perf_event |
CONFIG_CGROUP_PERF |
2.6.39 |
|
net_prio |
CONFIG_CGROUP_NET_PRIO |
3.3 |
|
hugetlb |
CONFIG_CGROUP_HUGETLB |
RESOURCE_COUNTERS和HUGETLB_PAGE |
3.5 |
pids |
CONFIG_CGROUP_PIDS |
4.3 |
|
rdma |
CONFIG_CGROUP_RDMA |
4.11 |
使用
查看子系统与层级关联情况
使用cat /proc/cgroups可以查看当前系统中可用的cgroup子系统与层级之间的关系;以Ubuntu 18.04为例:
1 | ~$ cat /proc/cgroups |
结果从左到右依次为:子系统名,与子系统关联的层级ID,该层级中cgroup的数量,子系统是否启用。
当系统中没有挂载任何层级时,结果如下
1 | ~$ cat /proc/cgroups |
创建新的层级
使用mount -t cgroup可以看到系统中当前挂载的层级
1 | ~$ mount -t cgroup |
在创建新的层级关联子系统之前,需要先确定subsystem是否已经关联其他层级,如果有,需要先卸载该层级。如上图结果中,如果需要卸载freezer子系统关联的层级,可以使用umount /sys/fs/cgroup/freezer卸载。
创建cgroup层级直接在挂载cgroup文件系统即可,一般挂载在/sys/fs/cgroup/下,挂载在其他路径也可以。
1 | mkdir -p /run/cgroup/memory |
当层级不与任何子系统关联,挂载时指定的参数name=<name>,<name>为该层级的唯一标记;当挂载另一个不关联子系统的层级时,如果参数name=<name>指定的<name>已经存在,则会再次挂载该层级,两个挂载点的内容相同。
1 | ~$ mkdir -p /run/cgroup/nametest |
查看进程属于哪些cgroup
使用cat /proc/<进程号>/cgroup查看进程属于哪些cgroup,例如
1 | ~$ cat /proc/1/cgroup |
结果从左到右依次为:所属层级的ID,与层级关联的子系统,在层级的目录树中所属的cgroup的路径。