编辑
2026-01-31
记录知识
0
请注意,本文编写于 98 天前,最后修改于 98 天前,其中某些信息可能已经过时。

目录

virtual runtime
总结
参考

之前讨论的CFS的weight,通过weight的设置,可以使得其相比于步幅调度具备局部更多的公平,本文进一步的讨论vruntime是的计算方式,有些大的公式在讨论权重的时候已经介绍一点了。

virtual runtime

回顾公式vruntime += delta * nice0 / weight,可以看到,cfs调度器通过vruntime来平衡任务的公平性,所以在cfs中,我们不能单看weight这一个影响因子,只需要看vruntime的大小就能知道一个任务的优先级顺序,vruntime越小,则越容易被调度。

我们跟踪代码,看看vruntime是怎么自加的

update_curr curr->vruntime += calc_delta_fair(delta_exec, curr); delta = __calc_delta(delta, NICE_0_LOAD, &se->load);

其核心计算函数为

/* * delta_exec * weight / lw.weight * OR * (delta_exec * (weight * lw->inv_weight)) >> WMULT_SHIFT * * Either weight := NICE_0_LOAD and lw \e sched_prio_to_wmult[], in which case * we're guaranteed shift stays positive because inv_weight is guaranteed to * fit 32 bits, and NICE_0_LOAD gives another 10 bits; therefore shift >= 22. * * Or, weight =< lw.weight (because lw.weight is the runqueue weight), thus * weight/lw.weight <= 1, and therefore our shift will also be positive. */ static u64 __calc_delta(u64 delta_exec, unsigned long weight, struct load_weight *lw) { u64 fact = scale_load_down(weight); int shift = WMULT_SHIFT; __update_inv_weight(lw); if (unlikely(fact >> 32)) { while (fact >> 32) { fact >>= 1; shift--; } } fact = mul_u32_u32(fact, lw->inv_weight); while (fact >> 32) { fact >>= 1; shift--; } return mul_u64_u32_shr(delta_exec, fact, shift); }

上述代码的公式

vruntime_delta = delta_exec * (weight / lw->weight) = (delta_exec * weight * lw->inv_weight) >> WMULT_SHIFT #define WMULT_SHIFT 32

这个在权重篇介绍过,inv_weight 是 weight 的速算表。此时我们再代入公式vruntime += delta * nice0 / weight可以将公式抽象成如下

vruntime_delta = wall_time_delta * (NICE_0_weight / NICE_k_weight) = wall_time_delta * (NICE_0_weight * 2^32 / (NICE_k_weight * 2^32)) = (wall_time_delta * (NICE_0_weight * 2^32 / NICE_k_weight)) >> 32 = (wall_time_delta * NICE_0_weight * (2^32 / NICE_k_weight)) >> 32

注意其中2^32 / NICE_k_weight其实就是sched_prio_to_wmult本存放在load_weight结构上

struct load_weight { unsigned long weight; u32 inv_weight; };

回到代码__calc_delta上,实际上是分两个步骤上计算的。
步骤1,fact = mul_u32_u32(fact, lw->inv_weight);
这里计算公式为

fact = (weight / lw->weight) * 2^32

步骤2,mul_u64_u32_shr(delta_exec, fact, shift);
这里计算公式为

delta_exec * fact >> 32

两个公式整合就是原公式了。

vruntime_delta = delta_exec * (weight / lw->weight)

总结

本文介绍了vruntime的公式由来,可以清晰的知道vruntime的计算公式,如果想了解此计算公式的可以详细查看一下,不过一般调试过程中不会太关注这个公式,本文只是知识归纳总结一下而已。

参考

http://www.wowotech.net/process_management/447.html