1. 概述
Completely Fair Scheduler
,完全公平调度器,用于Linux系统中普通进程的调度。
CFS
采用了红黑树算法来管理所有的调度实体sched_entity
,
算法效率为O(log(n))。
CFS跟踪调度实体sched_entity
的虚拟运行时间vruntime,
平等对待运行队列中的调度实体sched_entity
,将执行时间少的调度实体sched_entity
排列到红黑树的左边。
老规矩,先上张图片来直观了解一下原理:
每个sched_latency
周期内,根据各个任务的权重值,可以计算出运行时间runtime;
运行时间runtime
可以转换成虚拟运行时间vruntime
;
根据虚拟运行时间的大小,插入到CFS
红黑树中,虚拟运行时间少的调度实体放置到左边;
在下一次任务调度的时候,选择虚拟运行时间少的调度实体来运行;
在开始本文之前,建议先阅读下(一)Linux进程调度器-基础
。
开始探索之旅!
2. 数据结构
2.1 调度类
Linux内核抽象了一个调度类struct sched_class
,这是一种典型的面向对象的设计思想,将共性的特征抽象出来封装成类
在实例化各个调度器的时候,可以根据具体的调度算法来实现。
这种方式做到了高内聚低耦合,同时又很容易扩展新的调度器。
在调度核心代码kernel/sched/core.c
中,使用的方式是task->sched_class->xxx_func
其中task表示的是描述任务的结构体struct task_struck
,在该结构体中包含了任务所使用的调度器
进而能找到对应的函数指针来完成调用执行,有点类似于C++中的多态机制。
2.2 rq/cfs_rq/task_struct/task_group/sched_entity
struct rq
:每个CPU都有一个对应的运行队列;
struct cfs_rq
:CFS运行队列,该结构中包含了struct rb_root_cached
红黑树,
用于链接调度实体struct sched_entity
。
rq运行队列中对应了一个CFS运行队列,此外,在task_group
结构中也会为每个CPU再维护一个CFS运行队列;
struct task_struct
:任务的描述符,包含了进程的所有信息,该结构中的struct sched_entity
,用于参与CFS的调度;
struct task_group
:组调度(参考前文),Linux支持将任务分组来对CPU资源进行分配管理,
该结构中为系统中的每个CPU都分配了struct sched_entity
调度实体和struct cfs_rq
运行队列
其中struct sched_entity
用于参与CFS的调度;
struct sched_entity
:调度实体,这个也是CFS调度管理的对象了;
来一张图看看它们之间的组织关系: