cgroup是LXC的内核实现机制,LXC即是Linux Containers,是一种轻量级的虚拟化方案,它利用cgroup机制在内核代码上实现了进程分组控制和组进程的资源隔离,由于是充分利用了内核现有机制,不像KVM等虚拟机那样实现指令解释等复杂操作,LXC利用效率高,部署速度快,在资源控制隔离等场景应用上更高效。下面主要了解一下LXC依赖的内核机制cgroup的具体实现,关于LXC的具体代码,有机会再写。

一个功能完备的资源隔离方案需要有以下功能支持:

  1. 对用户态提供对应接口,使用户态能直接控制内核。
  2. 对进程有效隔离,同时能控制进程的生命周期。
  3. 对资源进行有效分配控制,常用的资源有CPU时间,内存,IO,网络等设备。
  4. 对资源使用情况能有效记录。

对于用户态接口,cgroup设计了cgroup文件系统,使用户态通过文件读写将控制信息传递给内核(一切即文件的思想)。
进程隔离则是使用了进程组和namespace配合搞定
资源控制分配则是根据内核现有的控制机制,将用户态控制参数传递给内核对应的点,具体后续写。
资源的记录则是内核变化在用户态展现,比较简单。

cgroup是一个树状结构分布,系统启动的时候会创建一个cgroup系统,在start_kernel函数中,调用cgroup_init。cgroup_init比较简单,就是用kobject_create_and_add创建kobject,用register_filesystem注册了cgroup文件系统,用proc_create在proc下创建了cgroup开关。具体代码流程后面再看,先看框架内容。

就像它目录呈现的那样,可以这么理解Cgroup, 下面以ubuntu为例,3.13.0-24-generic内核代码,

首先有一个全局的root目录,是总控制开关:

oenhan@oenhan /sys/fs/cgroup $ ls
blkio  cpu  cpuacct  cpuset  devices  freezer  hugetlb  memory  perf_event  systemd

下面的目录就是各个子系统的控制开关,各个子系统如目录名所示,控制CPU的,内存的,等。事实上各个子系统的可以重叠到一个目录上控制的,如下:

mount -t cgroup -o cpu,cpuset,memory cpu_mem /cgroup/key

上面就是把cpu,cpuset,memory的3个子系统开关放到一个目录下控制,但个人看子系统重叠容易导致系统复杂度提高,而且管理容易混乱。而Ubuntu系统默认的管理方式,则简单明了,虽然可能不满足一个进程组直接控制的理想方案。

以cpu子系统为例看一下:

oenhan@oenhan /sys/fs/cgroup/cpu $ ls
cgroup.clone_children  cgroup.procs          cpu.cfs_period_us  cpu.shares  machine            release_agent  user
cgroup.event_control   cgroup.sane_behavior  cpu.cfs_quota_us   cpu.stat    notify_on_release  tasks

oenhan@oenhan /sys/fs/cgroup/cpu $ cat tasks | wc -l
252

cpu下的很多控制文件后面细说,可以看一下tasks文件,里面即是系统当前的进程号,因为cpu是子系统的root,而OS中肯定有一个root_cgroup,所以tasks下是系统所有的进程。这里面的所有进程都会受当前目录下的控制文件限制,即CPU的使用率限制。这些tasks组成了一个进程组
但是进程组中的每个进程也会被区别对待的,这个就用到了树状结构的处理,

oenhan@oenhan /sys/fs/cgroup/cpu/ $ mkdir cpu_son
oenhan@oenhan /sys/fs/cgroup/cpu/cpu_son $ ls
cgroup.clone_children  cgroup.procs       cpu.cfs_quota_us  cpu.stat           tasks
cgroup.event_control   cpu.cfs_period_us  cpu.shares        notify_on_release
oenhan@oenhan /sys/fs/cgroup/cpu/cpu_son $ cat tasks  | wc -l
0

进程组的进一步分化也是通过mkdir创建新的子系统控制目录进行的,cpu_son下tasks即是新的子进程组,需要你手工往里面添加进程。如果再分化再添加子目录,构成了一个树状结构,所有子目录下的子系统属性都是继承了当前root目录的系统属性,即CPU目录下创建的cpu_son默认也只是CPU子系统控制目录,而不带memory控制功能。
各个子系统的操作和cpu系统类似。

有了直观认识之后在看一些概念东东:
1.control group:进程组控制群,进程按照一定标准划分到一起,进行资源分配控制的单元
2.hierarchy:层级,每个进程组都会细分成不同的资源分配实体(子进程组),如此,就产生了下一个层级
3.subsytem:子系统,进程组按照资源不同划分,而子系统就是每种资源的抽象概念,如CPU对应CPU系统,另外子系统还包括一些抽象接口。

先写这么多,具体子系统的代码实现,后面慢慢写。


Cgroup源码分析1:基本概念与框架来自于OenHan

链接为:https://oenhan.com/cgroup-src-1

1 thought on “Cgroup源码分析1:基本概念与框架”

发表回复