# 2.6.3.3 组调度 - 时间分配

如果se代表的是任务组，那么该se在当前cfsrq中根据权重分配到的时间还需要在自己的任务组内进行二次分配。为se计算时间份额的函数是 `sched_slice`, 该函数的逻辑在调度周期中已经分析过，这里我们再看一下该函数对任务组的处理方式：

```
/* file: kernel/sched/fair.c */
static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se) {
unsigned int nr_running = cfs_rq->nr_running;
u64 slice;

/* 调度周期 */
slice = __sched_period(nr_running + !se->on_rq);

/* 处理任务组的循环，颜色se的parent一路往上爬升 */
for_each_sched_entity(se) {
struct load_weight *load;
struct load_weight lw;

cfs_rq = cfs_rq_of(se);
/* 整个运行队列 cfs_rq 的总权重 */
load = &cfs_rq->load;

/* 从时间总额slice中为se分配其应得的份额，根据se在整个队列中的权重比例进行分配 */
slice = __calc_delta(slice, se->load.weight, load);
}

if (sched_feat(BASE_SLICE))
slice = max(slice, (u64)sysctl_sched_min_granularity);

return slice;
}

#define for_each_sched_entity(se) for (; se; se = se->parent)
```

任务组内部对时间做二次分配的算法思路也是一样的，即根据目标 `se` 与任务组的总体权重比例进行分配。我们知道一个任务组的所有调度实体都在一个cfsrq中，代码通过 `se->parent` 一路往上走，依次计算出每个任务组中的时间配额，循环结束后即得到 `se` 最终的时间配额。我们通过一个示意图来理解总体流程：&#x20;

![](https://640510796-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-3_JXLYv-4hrEXyDb%2Fuploads%2FYSXlhaeCTnyqiBnWzVpd%2Ftask_group_slice_calc.png?alt=media\&token=a797869e-f933-4c49-860d-40ead8ae0761)

图中目标的调度实体为 `SE2`, 其最终的时间配额结果是 `slice0 = slice * r2 * r1 * r0`, 其中 `slice` 是总时间，可以看出不管任务组嵌套多少层，目标调度实体不管处在哪一层，最终都可以正确计算出其应该分配到的时间配额。
