cgroup在Linux的代码里面已经很久了,但是对于搞嵌入式的我来说,最近才觉得这东西离我也蛮近的,为啥,当然是android 性能了。
网上看到了一个关于cgroup的系列博文 http://blog.csdn.net/wudongxu/article/details/8474198 ,讲的非常好。
cgroup就是control group,就是将一个或者多个task组成一个group,cgroup对这个group的资源进行控制。具体实现依赖于具体的cgroup sub system的实现。
为啥要开发cgroup呢? 打个比方你们组的成员公用一台服务器,现在某个人需要编译代码“make -j 20",然后服务器开始编译代码,其余人的体验就变差,变得很卡,影响工作。
你这时候就会想是不是可以给每个人分配一个最大资源的限制,这样一个人编译代码不会影响到别人的工作。cgroup就是这个用途。
图一:CPU子系统
这是一个cpu子系统被挂载之后的截图,除了cgroup前缀的控制文件,cpu前缀的cpu子系统私有文件之外,
还创建了一个bg_non_interactive的子目录。
“echo pid > tasks" 可以将一个进程加到cgroup组中,"echo pid > cgroup.procs"可以将一个线程组加到
cgroup组中。
这里就直接盗图了,关于cgroup代码的部分可以参照上面提到的系列博文。
图二:Cgroup结构体关系图
虽然这张图并不是很合我的意,但是很好的说明了各个结构体之间的关系。
刚才说到了cgroup用于控制一个或者多个进程,并对其资源进行限制。那么cgroup必然跟task_struct有关联。
task_struct代表着一个具体的进程,struct cgroup代表一个具体的cgroup组。一个进程可以在多个不同的(cpu,blkio)cgroup组中;
而一个cgroup组中可能存在一个或者多个进程。那么cgroup与task_struct就必然是一个M:N的多对多的关系。
所以通过cg_cgroup_link来实现这种多对多的关系。
我们可以通过"mount -t cgroup -o cpu,blkio none /sys/fs/cgroup" 这样来一次性挂载多个子系统。所以cgroup与cgroup_subsys_state是一对多的关系。
所以cgroup中维护了一个cgroup_subsys_state *subsys[]的指针数组,用于实现一对多的关系。
关于如何使用cgroup,网上一大堆的描述,最直观的就是"echo pid > /1/2/3/tasks"
这个目录/1/2就对应着一个cgroup(struct cgroup),就是一个控制组。通过
"echo pid > /1/2/tasks"命令
可以将一个具体的进程添加到这个cgroup组中,受到cgroup的约束。
假如最开始是将一个子系统挂载到目录/1 下面“mount -t cgroup -o cpu none /1"
通过"cd /1/ & mkdir /1/2 " 创建了/1/2子目录。这样就出现了一个呈现拓扑结构的cgroup组关系。
图三:进程关系图
这里大概的话了一个简单的拓扑图。根目录/1下面存在ABC三个字进程,子目录/1/2下面存在EFG三个子进程。
在scheduler里面,cgroup 2同样是一个sched_entity,其地位跟ABC是一样的,并没有因为它是一个task_group
组而有所变化。2这个sched entity被选中时,其会继续从EFG中进行调度选中一个具体的进程。
-
/* Walk up scheduling entities hierarchy */
-
#define for_each_sched_entity(se) \
-
for (; se; se = se->parent)
scheduler根据sched entity的 my_q字段来判断一个entity是一个进程还是一个task_group。
图四:进程结构体关系图
还有一点关于cgroup初始化中,有一个early_init变量。为什么需要在cgroup_init_eraly(由start_kernel直接调用)中初始化eraly_init =1的sub system呢?
由于CPU子系统涉及到进程调度,cpu子系统需要初始化0号进程的css_set,并将0号进程至于cpu子系统的根目录之下,这样之后所有新创建的进程都会默认
处于cpu子系统的根目录之下,这样会方便于之后的操作。
打个比方,以上面图一中的bg_non_interactive,这个是android为了限制后台进程而创建的一个cgroup,你可以通过“echo pid > /dev/cpuctl/bg_non_interactive"将
一个进程置为后台进程。这时候你可能会想,其余的用户进程在哪里?内核进程呢?会不会有一些进程没有在cgroup的管理中而导致它们之间显著的差异 ?
不用怕,其余进程在根目录下面。
阅读(3959) | 评论(0) | 转发(0) |