Chinaunix首页 | 论坛 | 博客
  • 博客访问: 68139
  • 博文数量: 19
  • 博客积分: 425
  • 博客等级: 下士
  • 技术积分: 239
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-08 15:35
文章分类

全部博文(19)

文章存档

2012年(2)

2011年(17)

我的朋友

分类: LINUX

2012-12-04 14:11:19


CFS调度中 cpu control group与组(task group)调度

will.huang@aliyun-inc.com

最近一直在理cpu control group的实现,其中有几个比较难理解的地方,就顺便整理了一下,理解下面的内容需要一定的cfs调度基础和control group的基本概念。Cfs调度中有个重要的概念就是sesched_entity),每个task都对应一个se,但是反之不成立,并不是每个se都对应一个task。之所以这样,是因为组(task_group)的存在。 而组和cpu control group之间又是相互依赖。Cpu control group就是利用了task_group当做一个调度实体实现了处理器在不同组间的划分。

1Cgrouptask_cgroup的对应

假设我们现在有如下拓扑结构的cgroup,同时这个cgroup所在的机器有两个core,那么在此机器上rq[cpu]有两个对象rq[0]rq[1]。每个cgroup节点对应一个task_group具体可通过下面函数获取相应的对应关系。

 

static inline struct task_group *cgroup_tg(struct cgroup *cgrp)

{

    return container_of(cgroup_subsys_state(cgrp, cpu_cgroup_subsys_id),

                struct task_group, css);

}

该操作用来将cgroup转换到task_group结构, cgroup_subsys_state(cgrp, cpu_cgroup_subsys_id)用来取得cgroup,cpu subsys对应的struct cgroup_subsys_state结构,然后调用container_of()取得task_group。从这个转换可知一个cgroup节点对应一个task_group结构。

2task_group中的关键数据结构于组调度

除了cgroup的层次关系可以确定task_group之间的层次关系外,task_group还通过parentsilbing children指针链接层一棵树。Task_group的数据成员如下所示:

struct {

        struct ;

#ifdef

    /*每个cpu都对应一个sched_entity*/

        /* schedulable entities of this group on each cpu */

        struct **;

        /* runqueue "owned" by this group on each cpu */

/*每个cpu都对一个cfs_rq*/

        struct **;

/*调度组的shares*/

        unsigned long ;

        ;

#endif

                                         …………………………..

        struct *;

        struct ;

        struct ;

#ifdef

        struct *;

#endif

        struct ;

};

 

Task_group中有两个重要的数据结构分别是se[cpu]csf_rq[cpu](我们这边只关注cfs,因此rt相关的自动滤去)。以上图中的拓扑结构为例,添加上相应的secfs_rq对应信息如下所示:

Root group中对应的调度队列直接就是cpu_rq,而下层的每个group都有自己的cfs_rq。如果没有task_group的存在那么每个se都应该出现在cpu_rq中就是cpu_rq[0]cpu_rq[1]中参与cfs调度。由于task group的存在从上图可知,在cpu_rq[0]cpu_rq[1]中的se分别只有:cpu_rq[0]:{seA0,SeB0}; cpu_rq[1]:{seA1,SeB1}。而task Ctask对应的se都存储在task_group自己的调度队列中(task CTask Dse就只存在于Group C自己allocate出来的cfs_rq中)。那么在全局调度层面cfs只能选择task_group对应的se,而这些se并不是可执行的task,因此在选择下一个sched_entity时需要遍历相应se的子节点,选择一个真正的task执行,代码如下所示:

static struct task_struct *pick_next_task_fair(struct rq *rq)

{      

        struct task_struct *p;

        struct cfs_rq *cfs_rq = &rq->cfs;

        struct sched_entity *se;

        if (unlikely(!cfs_rq->nr_running))

                return NULL;

        do {

                se = pick_next_entity(cfs_rq);

                set_next_entity(cfs_rq, se);

                cfs_rq = group_cfs_rq(se);

        } while (cfs_rq);

        p = task_of(se);

        hrtick_start_fair(rq, p);

        return p;

}

这样设计的好处是将task_group当做一个整体,参与到cfs的调度中,就可以通过cgrouptask进行分组,以组参与cpu时间的划分。假设图一中箭头上的权值作为每个group的权重(即task_group中的shares)参与处理器的分成。这个shares只是标注了某个group下面的子se对属于此group的时间划分。比如group A下面的task Agroup C将按照512:10241:2)划分属于group A的时间。Cfs如何在在组间按照shares划分,这个问题在cfs中有详细描述,他是利用了优先级对应的权重所实现,具体可以参考cfs相关文档。

按照拓扑图中的shares划分,可以看到cpu时间按如下划分:

Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-font-kerning:1.0pt;}
阅读(3468) | 评论(0) | 转发(0) |
0

上一篇:EPOLL Linux内核源代码实现原理分析

下一篇:没有了

给主人留下些什么吧!~~