cgroups

cgroups

介绍

CGroup 是 Control Groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离进程组 (process groups) 所使用的物力资源 (如 cpu memory i/o 等等) 的机制。

CGroup 相关概念解释

  • 任务(task)。在 cgroups 中,任务就是系统的一个进程;

  • 控制族群(control group)。控制族群就是一组按照某种标准划分的进程。Cgroups 中的资源控制都是以控制族群为单位实现。一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。一个进程组的进程可以使用 cgroups 以控制族群为单位分配的资源,同时受到 cgroups 以控制族群为单位设定的限制;

  • 层级(hierarchy)。控制族群可以组织成 hierarchical 的形式,既一颗控制族群树。控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性;

  • 子系统(subsystem)。一个子系统就是一个资源控制器,比如 cpu 子系统就是控制 cpu 时间分配的一个控制器。子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。

相互关系:

  • 每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认 cgroup(我们称之为 root cgroup,此 cgroup 在创建层级时自动创建,后面在该层级中创建的 cgroup 都是此 cgroup 的后代)的初始成员;

  • 一个子系统最多只能附加到一个层级;

  • 一个层级可以附加多个子系统;

  • 一个任务可以是多个 cgroup 的成员,但是这些 cgroup 必须在不同的层级;

  • 系统中的进程(任务)创建子进程(任务)时,该子任务自动成为其父进程所在 cgroup 的成员。然后可根据需要将该子任务移动到不同的 cgroup 中,但开始时它总是继承其父任务的 cgroup。

例如CGroup 层级关系显示,CPU 和 Memory 两个子系统有自己独立的层级系统,而又通过 Task Group 取得关联关系:

CGroup层级图

CGroup 技术可以被用来在操作系统底层限制物理资源,起到 Container 的作用。图中每一个 JVM 进程对应一个 Container Cgroup 层级,通过 CGroup 提供的各类子系统,可以对每一个 JVM 进程对应的线程级别进行物理限制,这些限制包括 CPU、内存等等许多种类的资源。例如:

CGroup 典型应用架构图

CGroup的子系统包括:

  • blkio 设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。
  • cpu 使用调度程序为cgroup任务提供cpu的访问。
  • cpuacct 产生cgroup任务的cpu资源报告。
  • cpuset 如果是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存。
  • devices 允许或拒绝cgroup任务对设备的访问。
  • freezer 暂停和恢复cgroup任务。
  • memory 设置每个cgroup的内存限制以及产生内存资源报告。
  • net_cls 标记每个网络包以供cgroup方便使用。
  • net_prio — 这个子系统用来设计网络流量的优先级
  • hugetlb — 这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统。
  • perf_event 增加了对每group的监测跟踪的能力,即可以监测属于某个特定的group的所有线程以及运行在特定CPU上的线程,此功能对于监测整个group非常有用
  • systemd

使用

在实际的使用过程中,你需要通过挂载(mount)cgroup文件系统新建一个层级结构,挂载时指定要绑定的子系统,缺省情况下默认绑定系统所有子系统。把cgroup文件系统挂载(mount)上以后,你就可以像操作文件一样对cgroups的hierarchy层级进行浏览和操作管理(包括权限管理、子文件管理等等)。除了cgroup文件系统以外,内核没有为cgroups的访问和操作添加任何系统调用。

层级激活后,/proc目录下的每个task PID文件夹下都会新添加一个名为cgroup的文件,列出task所在的层级,对其进行控制的子系统及对应cgroup文件系统的路径。

一个cgroup创建完成,不管绑定了何种子系统,其目录下都会生成以下几个文件,用来描述cgroup的相应信息。同样,把相应信息写入这些配置文件就可以生效,内容如下。

  • tasks:这个文件中罗列了所有在该cgroup中task的PID。该文件并不保证task的PID有序,把一个task的PID写到这个文件中就意味着把这个task加入这个cgroup中。
  • cgroup.procs:这个文件罗列所有在该cgroup中的线程组ID。该文件并不保证线程组ID有序和无重复。写一个线程组ID到这个文件就意味着把这个组中所有的线程加到这个cgroup中。
  • notify_on_release:填0或1,表示是否在cgroup中最后一个task退出时通知运行release agent,默认情况下是0,表示不运行。
  • release_agent:指定release agent执行脚本的文件路径(该文件在最顶层cgroup目录中存在),在这个脚本通常用于自动化umount无用的cgroup。

除了上述几个通用的文件以外,绑定特定子系统的目录下也会有其他的文件进行子系统的参数配置。

在创建的hierarchy中创建文件夹,就类似于fork中一个后代cgroup,后代cgroup中默认继承原有cgroup中的配置属性,但是你可以根据需求对配置参数进行调整。这样就把一个大的cgroup系统分割成一个个嵌套的、可动态变化的“软分区”。

http://www.infoq.com/cn/articles/docker-kernel-knowledge-cgroups-resource-isolation/

subsystem配置参数用法

源代码

源代码在src/linux目录下,对linux相关的一些功能进行了包装。

cgroups

src/linux/cgroups.cpp

函数名称 功能 参数
mount mount cgroups虚拟文件系统到指定目录
umount umount cgroups虚拟文件系统指定的层次目录
cloneCpusetCpusMems 从父组中拷贝'cpuset.cpus' and 'cpuset.mems' 到子组
create 在给定的cgroups层次创建cgroup
move
read
write
prepare
verify
enable
hierarchies 返回cgroups的整个目录层次
hierarchy 返回cgroups的某个子系统的目录层次
enabled subsystems
busy
subsystems
subsystems hierarchy
mount hierarchy
subsystems
retry
unmount hierarchy
mounted hierarchy
subsystems
create

.....

代码都很直观,分析一个prepare作为例子:

prepare

参数:

  • const string& baseHierarchy,
  • const string& subsystem,
  • const string& cgroup

流程:

  • 415-423:内核是否已经支持cgroups?是否根用户权限运行?
  • 428-433:检查子系统是否已经安装到指定的层次目录上
  • 435-460:若没有,执行mount
  • 465-482:创建cgroup
  • .......

results matching ""

    No results matching ""