1. 概述
组调度(task_group)是使用Linux cgroup(control group)的cpu子系统来实现的,可以将进程进行分组,按组来分配CPU资源等。
比如,看一个实际的例子:
A和B两个用户使用同一台机器,A用户16个进程,B用户2个进程
如果按照进程的个数来分配CPU资源,显然A用户会占据大量的CPU时间,这对于B用户是不公平的。
组调度就可以解决这个问题,分别将A、B用户进程划分成组,并将两组的权重设置成占比50%即可。
带宽(bandwidth)控制,是用于控制用户组(task_group)的CPU带宽,通过设置每个用户组的限额值,可以调整CPU的调度分配。
在给定周期内,当用户组消耗CPU的时间超过了限额值,该用户组内的任务将会受到限制。
由于组调度和带宽控制紧密联系,因此本文将探讨这两个主题,本文的讨论都基于CFS调度器,开始吧。
2. task_group
•组调度,在内核中是通过struct task_group来组织的,task_group本身支持cfs组调度和rt组调度,本文主要分析cfs组调度。
•CFS调度器管理的是sched_entity调度实体,
task_struct(代表进程)和task_group(代表进程组)中分别包含sched_entity
进而来参与调度;
关于组调度的相关数据结构,组织如下:
•内核维护了一个全局链表task_groups,创建的task_group会添加到这个链表中;
•内核定义了root_task_group全局结构,充当task_group的根节点,以它为根构建树状结构;
•struct task_group的子节点,会加入到父节点的siblings链表中;
•每个struct task_group会分配运行队列数组和调度实体数组(以CFS为例,RT调度类似),其中数组的个数为系统CPU的个数,也就是为每个CPU都分配了运行队列和调度实体
对应到实际的运行中,如下:
struct cfs_rq包含了红黑树结构,sched_entity调度实体参与调度时,都会挂入到红黑树中,task_struct和task_group都属于被调度对象;
•task_group会为每个CPU再维护一个cfs_rq,这个cfs_rq用于组织挂在这个任务组上的任务以及子任务组,参考图中的Group A;
•调度器在调度的时候,比如调用pick_next_task_