Chinaunix首页 | 论坛 | 博客
  • 博客访问: 752204
  • 博文数量: 79
  • 博客积分: 2671
  • 博客等级: 少校
  • 技术积分: 1247
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-02 15:26
个人简介

宅男

文章分类

全部博文(79)

文章存档

2017年(11)

2016年(12)

2015年(6)

2012年(10)

2011年(33)

2010年(7)

分类: Android平台

2016-09-08 14:23:39

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中进行调度选中一个具体的进程。

  1. /* Walk up scheduling entities hierarchy */
  2. #define for_each_sched_entity(se) \
  3.                 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的管理中而导致它们之间显著的差异 ?
不用怕,其余进程在根目录下面。
阅读(4017) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~