A每6个时间片执行1个时间片,B每3个时间片执行1个时间片,C每2个时间片执行1个时间片
vruntime:
A: 0 6 6 6 6 6 6 12 12 12 12 12 12
B: 0 0 3 3 3 6 6 6 9 9 9 12 12
C: 0 0 0 2 4 4 6 6 6 8 10 10 12
调度: A B C C B C A B C C B C
提纲
CFS的原理
2. CFS 的实现
红黑树:CFS中进程vruntime数据结构
Linux 采用了红黑树记录下每一个进程的 vruntime
在多核系统中,每个核一棵红黑树
调度时,从红黑树中选取vruntime最小的进程出来运行
CFS 的进程权重
权重由 nice 值确定,权重跟进程 nice 值一一对应
nice值越大,权重越低
通过全局数组 prio_to_weight 来转换
CFS中新创建进程的 vruntime如何设置?
如果新进程的 vruntime 初值为 0 的话,比老进程的值小很多,那么它在相当长的时间内都会保持抢占 CPU 的优势,老进程就要饿死了,这显然是不公平的。
CFS中新创建进程的 vruntime设置
每个 CPU 的运行队列 cfs_rq 都维护一个min_vruntime 字段
记录该运行队列中所有进程的 vruntime 最小值
新进程的初始vruntime 值设置为它所在运行队列的min_vruntime
与老进程保持在合理的差距范围内
CFS中休眠进程的 vruntime 一直保持不变吗?
如果休眠进程的 vruntime 保持不变,而其他运行进程的 vruntime 一直在推进,那么等到休眠进程终于唤醒的时候,它的 vruntime 比别人小很多,会使它获得长时间抢占 CPU 的优势,其他进程就要饿死了。
在多 CPU 的系统上,不同的 CPU 的负载不一样,有的 CPU 更忙一些,而每个 CPU 都有自己的运行队列,每个队列中的进程的vruntime 也走得有快有慢,每个CPU运行队列的 min_vruntime 值,都会有不同
CFS中的进程迁移
当进程从一个 CPU 的运行队列中出来时,它的 vruntime 要减去队列的 min_vruntime 值;
当进程加入另一个 CPU 的运行队列时,它的vruntime 要加上该队列的 min_vruntime 值。
CFS的vruntime 溢出问题
vruntime 的类型 usigned long
进程的虚拟时间是一个递增的正值,因此它不会是负数,但是它有它的上限,就是unsigned long 所能表示的最大值
如果溢出了,那么它就会从 0 开始回滚,如果这样的话,结果会怎样?
CFS 的vruntime 溢出示例
unsignedchar a = 251;
unsignedchar b = 254;
b += 5;
//b溢出,导致a > b,应该b = a + 8//怎么做到真正的结果呢?改为以下:unsignedchar a = 251;
unsignedchar b = 254;
b += 5;
signedchar c = a - 250,
signedchar d = b - 250;
//到此判断 c 和 d 的大小