BetaThis is a live doc! Anyone with edit access can make updates in real time without having to publish.
cgroup v1

概念

多层级 multi-hierarchy

挂载一个 cgroup controller 到一个目录后,这个目录就成了一个 cgroup hierarchy

一个 cgroup hierarchy 下可以创建多个子目录,而每个字目录也都是一个子 hierarchy,二者构成「父子 cgroup 关系」,父 cgroup 的限制会同时应用于任何子 cgroup

但需要注意的是,每个 cgroup 的 cgroup.procstasks 只显示直接属于该 cgroup 的进程 / 线程而不会显示子 cgroup 中的进程 / 线程

cgroup.procs/tasks 文件

cgroup.procs 为 cgroup 管理的进程、tasks 为 cgroup 管理的线程

添加一个进程到 cgroup 时只需将它的 pid 加入到对应 cgroup hierchy 的 cgroup.procs 文件中即可

  • 当存在多个组 group 时,一个进程只能存在于一个 group 中,把它加入到一个 group 会自动将它从其他 group 中移出

  • 将一个进程加入至 cgroup.procs 文件时,会自动将它的所有子进程也加入、同时会自动将它的所有子线程加入 tasks

  • 将一个线程(或进程)加入至 tasks 文件时,只会将这个线程(或进程的主线程)加入,它所属的进程、所属的进程的其他子线程均不会进入

    • 注意,将线程加入至 tasks 文件时,是可以在 cgroup.procs 文件中看到这个线程所属的父进程的 pid 的,但是进程本身不受管理、且在 tasks 文件中也看不到进程的 id

从 cgroup 中移除任务

任何一个进程都会存在于 exactly 一个 cgroup 中

因此,不存在实际上的「移除」任务 —— 只能将任务移动到其他 cgroup —— 当然我们理解的删除往往就是移动到 root

named cgroup hierarchy

在 cgroups v1 中,可以利用如下命令挂载一个没有 controller 的 cgroup hierarchy(称为 named cgroup hierarchy)

1mount -t cgroup -o none,name=somename none /some/mount/point

这个 cgroup hierarchy 存在的唯一目的是跟踪进程(而不是管理进程);例如 systemd 便使用了这个能力

cgroup controller (subsystem)

cpu

cpu.shares

一个相对值(默认 1024),这个进程会被分配 指定的值 / 全局总值 这么多的 CPU 时间比例;因此,这个值用来调整一个任务占用 CPU 时间的权重而不是绝对的占用多少

另外,这个配置仅在繁忙时生效 —— 这指定的是可被分配到的 cpu shares 的最小值 —— 如果 CPU 本不繁忙则不会有限制

cpu.cfs_perios_us / cpu.cfs_quota_us / cpu.cfs_burst_us

  • cpu.cfs_period_us :周期的时间长度(微秒),后续所有配置都是相对于「这一个周期内」的限制;默认为 100_000(100ms)(最高可设置成 1s)

  • cpu.cfs_quota_us 一个周期内进程可使用的最大 CPU 时间(微秒),默认 -1 不限制,最少可设置成 1ms

  • cpu.cfs_burst_us 允许累积历史未使用的 CPU 时间供后续超出 quota 使用,这个配置指定可以累积的上限,默认为 0 不可累积

cpu.stat

包含给定 cgroup 的 CPU 统计值,类似

1nr_periods 0 2nr_throttled 0 3throttled_time 0 4nr_bursts 0 5burst_time 0
  • nr_periods: 已经过的 period 数量

  • nr_throttled: 被限制的次数

  • throttled_time: 被限制的总时间(以纳秒为单位)。

  • nr_bursts: 发生突发的 period 数量

  • burst_time: 共突发超额使用的累计 wall-time(以纳秒为单位)。

cpu.rt…

cpuacct

cpuset

memory

devices

freezer

注:freezer 在 root cgroup 不存在,必须创建子 cgroup hierarchy 来使用

freezer.state

freezer.state 是 freezer controller 唯一一个可读写的文件,用于查看和控制 freeze 的状态

设置时,可以设置为

  • THAWED - 解冻,即取消冻结(默认)

  • FROZEN - 冻结,即暂停所有进程的执行

在读取时,除了上面的两个状态,还有

  • FREEZING - 一个中间状态,在进程从未冻结转换为冻结态时会出现

另外,由于父 cgroup 同时会影响下层 cgroup,因此如果任何父级指定了 FROZEN 则为该 cgroup 始终为冻结状态

freezer.parent_freezing / freezer.self_freezing

0 - 未冻结,1 - 已冻结

freezer.state 在读取时读到的始终是「当前 cgroup 的实际冻结状态」,而这个会受本身是否冻结和父级是否冻结同时影响

freezer.parent_freezing 用于描述父级是否冻结、freezer.self_freezing 用于描述本级是否冻结

换句话说,在不考虑 FREEZING 状态的情况下,如果这两个文件任一为 1freezer.stateFROZEN、如果这两个文件全为 0freezer.stateTHAWED

net_cls

blkio

perf_event

net_prio

hugetlb

pids

rdma


参考

https://docs.kernel.org/admin-guide/cgroup-v1/cgroups.html