一、task_group
前面几章已经详细介绍了组调度的原因和创建,下面直接上关系说明和关系图。
- 组调度,在内核中是通过struct task_group来组织的,task_group本身支持cfs组调度和rt组调度,本文主要分析cfs组调度。
- CFS调度器管理的是sched_entity调度实体,task_struct(代表进程)和task_group(代表进程组)中分别包含sched_entity,进而来参与调度;
关于组调度的相关数据结构,组织如下:(网友的图很清楚了)
- 内核维护了一个全局链表task_groups,创建的task_group会添加到这个链表中;源码:LIST_HEAD(task_groups);
- 内核定义了root_task_group全局结构,充当task_group的根节点,以它为根构建树状结构;源码:struct task_group root_task_group;
- struct task_group的子节点,会加入到父节点的children链表中;
- 每个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_fair时,会从遍历队列,选择sched_entity,如果发现sched_entity对应的是task_group,则会继续往下选择;
- 由于sched_entity结构中存在parent指针,指向它的父结构,因此,系统的运行也能从下而上的进行遍历操作,通常使用函数walk_tg_tree_from进行遍历;
二 、task_group权重
- 进程或进程组都有权重的概念,调度器会根据权重来分配CPU的时间。
- 进程组的权重设置,可以通过/sys文件系统进行设置,比如操作/sys/fs/cgoup/cpu/A/shares;
调用流程如下图:
- sched_group_set_shares来完成最终的设置;
- task_group为每个CPU都分配了一个sched_entity,针对当前sched_entity设置更新完后,往上对sched_entity->parent设置更新,直到根节点;
- shares的值计算与load相关,因此也需要调用update_load_avg进行更新计算;
看一下实际的效果图吧:
- 写节点操作可以通