Linux进程调度原理

  • A+
所属分类:Linux系统

极简模式

假设我的系统只有一种调度算法cfs

那么有个调度的队列 cfs_rq

所有running的进程都会 进入这个队列,不在running 或者其他情况会出队列,ok。则假设队列控制的算法有以下。

cfs_rq_enqueue
cfs_rq_dequeue
cfs_rq_pick

所操作的是进程描述符 task_struck.

那么很简单可以理解上述过程

scehed_pick ---->cfs_rq_pick就行了。

 

多个调度算法

那么如果除了cfs还有rt算法

那么就有两个调度队列,cfs_rq和rt_rq。

一个进程task_struck 有可能属于cfs和rt。

那么考虑 scehed_pick 是如何pick?

ok,Linux建立一个sched_class 的结构链表,sched_class_cfs和sched_class_rt或者还有其他的。顺序的从这么多个调度算法中选择一个合适的。

stop_sched_class -> -> rt_sched_class -> fair_sched_class -> idle_sched_class

如上。那么问题来了,如果前面的队列一直满足,后面的队列就永远得不到执行,这些sched_class之间没有个合理的逻辑吗?

目前看到的逻辑,任务dl 是最先满足的,rt次之,cfs随后,idle当然是最后的,这样的逻辑,基本上能让人有点信服。

能信服,不够科学吧???还是有什么我没有看到的优先级。???

 

再抽象一层sched_entity

一般情况 cfs和rt或者其他的什么的调度算法的接口 enqueue或者dequeue 都是对task_struck 进行操作的。

但是Linux 这里再抽象一个sched_entity,每个task_struck 对应一个sched_entity 。调度算法对sched_entity操作就行了。

这样抽象我猜想有两个目的,一个是统一比较好看,和task_struck隔离。第二个是,为了下面的组调度做准备。

 

加入组调度

组调度的数据结构,和组织架构大概是如下这个样子

Linux进程调度 Linux进程调度

OK,如果Linux进行组调度,就不会说使用全局的cfs_rq队列,或者rt_rq队列。而是将这些队列分配到task_group中。大概流程是这样子的。

我们假设我们有两个组 GroupA 和GroupB A占2 B占1 就是有三次调用的情况下 A组会被调用两次,B组只有1次。

Linux进程调度原理

这个时候有一个进程启动了 task_struck task1

Linux进程调度原理

他选择A组,同理task2 可能也选择A task3可能选择B 如下

Linux进程调度原理

 

而A 和 B 不会记录 task的接口体,他记录task 的sched_entity 并用一个se[] 数组表示。

那么还有,task1 task2 有可能是cfs调度也有可能是rt,那么gruop结构体就用 cfs_se[] cfs_rq 和 rt_se[] rt_rq记录。

 

那么问题来了

 

task1 task2 属于cfs还是属于rt 是什么时候设置的?

在Android和linux里面没有看到,目前看到的是 0 也就是cfs,

那么有以下可能就是说,如果你不设置,就默认是0,或者继承父亲的等等这种默认策略。

 

scehed_pick 时候怎么pick?

按照pick三次 两次是A,ok。到了A,再使用这个策略

stop_sched_class -> dl_sched_class -> rt_sched_class -> fair_sched_class -> idle_sched_class

这个是说的通的。

但是要根据代码来。

接下来分析调度过程。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: