A每周期6时间片,B每周期3时间片,C每周期2时间片
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 的具体实现:
Linux 采用了一颗红黑树(对于多核调度,实际上每一个核有一个自己的红黑树),记录下每一个进程的 vruntime
需要调度时,从红黑树中选取一个 vruntime最小的进程出来运行
CFS 的具体实现:
权重如何决定?
权重由 nice 值确定,权重跟进程 nice 值之间有一一对应的关系
通过全局数组 prio_to_weight 来转换,nice值越大,权重越低。
CFS 的具体实现:
新创建进程的 vruntime 是多少?
假如新进程的 vruntime 初值为 0 的话,比老进程的值小很多,那么它在相当长的时间内都会保持抢占 CPU 的优势,老进程就要饿死了,这显然是不公平的。
CFS 的具体实现:
新创建进程的 vruntime 是多少?
每个 CPU 的运行队列 cfs_rq 都维护一min_vruntime 字段,记录该运行队列中所有进程的 vruntime 最小值
进程的虚拟时间是一个递增的正值,因此它不会是负数,但是它有它的上限,就是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 的大小