Skip to main content
  1. Docs/

Cgroup

·4 mins· ·
Cgroup Cgroup
Owl Dawn
Author
Owl Dawn
Table of Contents

Cgroup v2
#

Control Groups,linux 内核提供的物理资源隔离机制,实现对 linux 进程或进程组的资源限制、隔离和统计

功能

  • 资源限制
  • 优先级控制:不同的组可以有不同的优先级,如 CPU 使用、磁盘 IO
  • 审计:计算 group 的资源使用情况
  • 控制:挂起一组进程,或者重启一组进程

概念:

  • task:任务,对应于系统中运行的一个实体,一般为进程 ==(v2 已废弃)==
  • **subsystem:**子系统,具体的资源控制器(resource class 或者 resource controller),控制某个特定的资源使用。比如 CPU 子系统可以控制 CPU 时间,memory 子系统可以控制内存使用量
  • cgroup:控制组,一组任务和子系统的关联关系,表示对这些任务进行怎样的资源管理策略
  • hierarchy:层级树,一系列 cgroup 组成的树形结构。每个节点都是一个 cgroup,cgroup 可以有多个子节点,子节点默认会继承父节点的属性。系统中可以有多个 hierarchy

组成
#

cgroup 主要有两个组成部分:

  • core - 负责分层组织过程;
  • controller - 通常负责沿层次结构分配特定类型的系统资源。每个 cgroup 都有一个 cgroup.controllers 文件,其中列出了所有可供 cgroup 启用的控制器。当在 cgroup.subtree_control 中指定多个控制器时,要么全部成功,要么全部失败。在同一个控制器上指定多项操作,那么只有最后一个生效。每个 cgroup 的控制器销毁是异步的,在引用时同样也有着延迟引用的问题;

核心文件
#

文件 位置 作用 补充
cgroup.type 单值 非根 cgroup,可读写 通过将 “threaded” 写入该文件,将 cgroup 转换为线程 cgroup - domain: 正常的有效域 cgroup
- domain threaded 线程子树根的线程域 cgroup
- domain invalid: 无效的 cgroup
- threaded: 线程 cgroup,线程子树
cgroup.procs 换行分隔 所有 cgroup 都有; 可读写 每行列出属于 cgroup 的进程的 pid
cgroup.controllers 空格分隔 所有 cgroup 都有; 只读 显示 cgroup 可用的所有控制器 显示 cgroup 可用的所有控制器
cgroup.subtree_control 空格分隔 所有 cgroup 都有; 可读写 如果一个控制器在列表中出现不止一次,最后一个有效 初始为空
指定多个启用和禁用操作时,要么全部成功,要么全部失败。
"+" 启用;"-" 禁用
cgroup.events 非根 cgroup;只读 - populated: cgroup 及其子节点中包含活动进程,值为1;无活动进程,值为0
- frozen: cgroup 是否被冻结,冻结值为1;未冻结值为0.
cgroup.freeze 单值 所有 cgroup 都有; 可读写 冻结 cgroup 及其所有子节点 cgroup,会将相关的进程关停并且不再运行 默认值为0
完成后 events 文件中的 “frozen” 值更新为 1
冻结状态不会影响任何 cgroup 树操作(删除、创建等)
cgroup.kill 单值 非根 cgroup 上;可读写 将 cgroup 及其所有子节点中的 cgroup 杀死(进程会被 SIGKILL 杀掉) 唯一允许值为1
一般用于将一个 cgroup 树杀掉,防止叶子节点迁移
cgroup.max.descendants 单值 可读写 最大允许的 cgroup 数量子节点数量
cgroup.max.depth 单值 可读写 低于当前节点最大允许的树深度
cgroup.threads 换行分隔 所有 cgroup 都有; 可读写 每行列出属于 cgroup 的线程的 TID
cgroup.stat 只读 - nr_descendants:可见后代的 cgroup 数量
- nr_dying_descendants:被用户删除即将被系统销毁的 cgroup 数量

每个进程都属于一个 cgroup,一个进程的所有线程都属于同一个 cgroup。

迁移
#

通过将 PID 写入 cgroup 的 cgroup.procs 实现迁移 。进程的迁移不会影响现有的后代进程所属的 cgroup。

当一个进程 fork 出一个子进程时,该进程就诞生在其父亲进程所属的 cgroup 中。

如果 cgroup 中没有任何子进程或活动进程,可以删除目录,进行销毁(即使存在关联的僵尸进程,也被认为是可以被删除的)。

跨 cgroup 迁移进程代价较高,有状态的资源限制(如内存)不会动态应用于迁移

Cgroups
#

树状结构,每个非根 cgroup 含有一个 cgroup.events 文件,其中 populated 字段表示子树是否含有实时进程

所有非根的 cgroup.subtree_control 文件,只能包含在父级中启用的控制器。

cgroup 资源是自上而下分布约束的。只有当资源已经从上游 cgroup 节点分发给下游时,下游的 cgroup 才能进一步分发约束资源。

cgroup.subtree_control 文件只能包含在父节点的 cgroup.subtree_control 文件中启用的控制器内容。

非根 cgroup 只能在没有任何进程时才能将域资源分发给子节点的 cgroup,即 只有不包含任何进程的 cgroup 才能在其 cgroup.subtree_control 文件中启用域控制器,进程总在叶子节点上

挂载
#

  • memory_recursiveprot - 递归地将 memory.min 和 memory.low 保护应用于整个子树,无需显式向下传播到叶节点的 cgroup 中,子树内叶子节点可以自由竞争;
  • memory_localevents - 只能挂载时设置或者通过从 init 命名空间重新挂载来修改,这是系统范围的选项。只用当前 cgroup 的数据填充 memory.events,如果没有这个选项,默认会计数所有子树;
  • nsdelegate - 只能挂载时设置或者通过从 init 命名空间重新挂载来修改,这也是系统范围的选项。它将 cgroup 命名空间视为委托边界,这是两种委派 cgroup 的方式之一;

委派
#

两种方式:

  • 设置挂载选项 nsdelegate
  • 授权用户对目录及其 cgroup.procscgroup.threadscgroup.subtree_control 文件的写访问权限

两种方式的结果相同。一旦被委派,用户就可以在目录下建立子层次结构,所有的资源分配都受父节点的制约。目前,cgroup 对委托子层次结构中的 cgroup 数量或嵌套深度没有任何限制(之后可能会受到明确限制)。

参考资料
#

Related

Cgroup v1 和 v2 的区别
·1 min
Cgroup Cgroup
LevelDB
·13 mins
linux 文件系统
·12 mins
redis
·19 mins
一些 c++ 规范
·2 mins
Cpp Cpp
分布性一致算法
·10 mins