为了解决调度时时间分配的公平性问题,Linux 在2.16版本中引入了CFS(Complete Fair Scheduler). 早期的CFS实现只在进程层面上实现了时间的公平分配,例如,如果一个系统有100个进程,CFS会保证每个进程都获得1%的CPU时间,但实际上系统中的这100个进程可能隶属于两个用户A与B, 其中用户A拥有10个进程,用户B拥有90个进程,这种实现造成的结果是用户A只获得了10%的CPU时间,而用户B获得了90%的时间。如果用户B了解CFS的调度原理,那么他可以肆无忌惮地fork出更多的进程以攫取更多的CPU时间。可见CFS在进程层面上的公平,却导致了系统在用户层面上的不公平,甚至是漏洞。对于这种情况,一种更合理的策略是系统首先保证每个用户获得相同的时间,然后再对隶属于同一个用户的所有进程公平地分配该用户的时间。
将该概念进一步抽象,我们就得到了进程组的概念。进程组的引入实际上是增加了一个调度层级,调度器首先完成进程组的时间分配,再处理组内进程之间的时间分配,前文提到的用户分组只是进程组的一个特例。
/* file: include/linux/sched.h */
struct task_struct {
/* 调度实体,调度器的调度对象,该字段用于 CFS */
struct sched_entity se;
/* 该字段用于 RT 调度器 */
struct sched_rt_entity rt;
#ifdef CONFIG_CGROUP_SCHED
struct task_group *sched_task_group;
#endif
/* 该字段用于 DL 调度器 */
struct sched_dl_entity dl;
}