Linux调度器的演变
轮转调度RR
Round Robin
完全公平调度器CFS
Complete Fair Schedule
异构多处理HMP
Heterogeneous Multi-Processing
功耗感知调度EAS
Enery Aware Schedule
CFS 调度器概念 ( 完全公平调度器 )
CFS 调度器 ( Completely Fair Scheduler ) 是 " 完全公平调度器 " , " 完全公平调度算法 " 对每个 进程 都是公平的 ,
" 完全公平调度算法 " 是 基于时间片轮询 的 调度算法 ,
每个进程 都会获得一段 相同的大小的 CPU 时间片 来运行 ;
CFS 调度器 没有 时间片概念 , 该调度器会 公平地 分配 CPU 的使用时间 ;
举例说明 : 如果有 4 个相同 优先级 的进程运行在 同一个 CPU 上 , 每个进程都会被 公平 分配到 25% 的运行时间 ;
CFS 调度器虚拟时钟概念 ( Virtual Runtime )
CFS 调度器 中 , 定义了 一种 " 调度模型 " , 该 模型 为 CFS 执行队列 cfs_rq
中的 每个进程 都设置了 虚拟时钟 Virtual Runtime ;
被设置了 虚拟时钟 的进程 , 执行 n 时长后 , 其 虚拟时钟 会增加 n 时长 , 其它 没有执行的进程 虚拟时钟 值保持不变 ;
进程优先级 ( 调度优先级 | 静态优先级 | 正常优先级 | 实时优先级 )
进程优先级相关字段
在 linux-5.6.18\include\linux\sched.h 头文件中 task_struct
" 进程描述符 " 结构体 中定义了 进程优先级字段如下 :
int prio; // 调度优先级
int static_prio; // 静态优先级
int normal_prio; // 正常优先级
unsigned int rt_priority; // 实时优先级
1、prio 字段 ( 调度优先级 )
prio 字段 是 " 调度优先级 " , 数值越小 , 优先级越高 ;
一般情况下 prio 字段 等于 normal_prio 字段 ;
特殊情况 : 在锁同步机制中 , 如果 A 进程 占有了 实时互斥锁 , B 进程 等待该 实时互斥锁 , 假如 B 进程的优先级 高于 A 进程 的优先级 , 此时就会将 占有 实时互斥锁 的 A 进程的 prio 优先级 提高到与 B 进程 prio 优先级相等的地位 ;
2、static_prio 字段 ( 静态优先级 )
static_prio 字段 是 " 静态优先级 " ,
对于 " 限期进程 " 来说 , 静态优先级 static_prio 字段 值总为 0 , 没有意义 ;
对于 " 实时进程 " 来说 , 静态优先级 static_prio 字段 值总为 0 , 没有意义 ;
对于 " 普通进程 " 来说 , 静态优先级 static_prio 字段 值为 120 + nice , 其数值越小 , 优先级越高 ;
3、normal_prio 字段 ( 正常优先级 )
normal_prio 字段 是 " 正常优先级 " , 数值越小 , 优先级越高 ,
对于 " 限期进程 " 来说 , 正常优先级 normal_prio 字段 值总为 -1 ;
对于 " 实时进程 " 来说 , 正常优先级 normal_prio 字段 值 99 - rt_priority ;
对于 " 普通进程 " 来说 , 正常优先级 normal_prio 字段 值 与 静态优先级 static_prio 字段相等 , 为 120+nice , 其数值越小 , 优先级越高 ;
4、rt_priority 字段 ( 实时优先级 )
rt_priority 字段 是 " 实时优先级 " ,
对于 " 限期进程 " 来说 , 实时优先级 rt_priority 字段 值总为 0 , 没有意义 ;
对于 " 实时进程 " 来说 , 实时优先级 rt_priority 字段 值为 1~99 , 其数值越大 , 优先级越高 ;
对于 " 普通进程 " 来说 , 实时优先级 rt_priority 字段 值总为 0 , 没有意义 ;
Linux系统中进程的nice值与优先级
https://blog.youkuaiyun.com/qq_39599464/article/details/114402346
CFS 调度器 " 权重 " 概念
CFS 调度器 ( Completely Fair Scheduler ) " 完全公平调度器 " ,实际运行过程中 ,会涉及到 具有 不同 " 进程优先级 " 的 进程 之间的调度 , 有些进程 优先级高 , 有些进程 优先级低 ,为了避免 优先级低 的进程 始终无法得到 CPU 时间 执行 , 向每个进程提供 公平 调度 , CFS 调度器 引入了 " 权重 " 概念 , CFS 使用 " 权重 " 值 , 替代 进程的 优先级 , 不同 " 进程优先级 " 的进程 会按照 权重比例 , 分配 CPU 的执行时间。
CFS 调度器调度实例 ( 计算进程 " 实际运行时间 " )
有 2 个进程 A 和 B , 在 CPU 上执行 ;
A 进程的 权重 为 512 , B 进程的 权重 为 1024 ;
在 CPU 上执行的进程 可获取到的 CPU 时间比例 计算公式如下 :
A进程获取的CPU时间比例 = 所有进程的权重之和 / A进程权重
A 进程获取的CPU 时间比例 = A 进程权重 / 所有进程的权重之和 = 512 / (512 + 1024) = 1 / 3
CPU 的总时间是 CPU的调度区(调度周期)
大小 , 则 进程 在 CPU 上执行的进程 可获取到的 CPU时间
计算公式如下 :
进程获取的CPU时间 = 调度区 × 所有进程的权重之和 / 进程权重
计算进程 " 虚拟运行时间 "
虚拟运行时间的引入
CFS为了实现公平,必须惩罚当前正在运行的进程,以使那些正在等待的进程下次被调度。
具体实现时,CFS通过每个进程的虚拟运行时间(vruntime)来衡量哪个进程最值得被调度。
CFS中的就绪队列是一棵以vruntime为键值的红黑树,虚拟时间越小的进程越靠近整个红黑树的最左端。因此,调度器每次选择位于红黑树最左端的那个进程,该进程的vruntime最小
虚拟运行时间是通过进程的实际运行时间和进程的权重(weight)计算出来的。
在CFS调度器中,将进程优先级这个概念弱化,而是强调进程的权重。一个进程的权重越大,则说明这个进程更需要运行,因此它的虚拟运行时间就越小,这样被调度的机会就越大。
那么,在用户态进程的优先级nice值与CFS调度器中的权重又有什么关系?在内核中通过prio_to_weight数组进行nice值和权重的转换。
每一个进程拥有一个vruntime,每次需要调度的时候就选运行队列中拥有最小vruntime的那个进程来运行,vruntime在时钟中断里面被维护,每次时钟中断都要更新当前进程的vruntime,即vruntime以如下公式逐渐增长:
http://t.zoukankan.com/linhaostudy-p-9946814.html
通过上述公式 , 可以得出 :
在 相同的 调度周期 中 , 所有 运行在该 CPU 上的进程 的 " 虚拟运行时间 " 是相同的 ,
在 CFS 调度器 对 进程 进行调度运行时 , 找到 " 虚拟运行时间 " 最小的进程 运行即可 ,
Linux 内核中 , 进程队列 的数据结构是 " 红黑树 " , 该数据结构 可以最快地找到 " 虚拟运行时间 " 最小的进程 ;