完全公平调度程序(CFS):长时间运行进程的vruntime

lis*_*reg 7 linux scheduler linux-kernel cfs

如果自创建流程以来计算了vruntime,那么如果这个流程与新创建的处理器绑定流程竞争,那么这个流程怎么会得到处理器呢?

正如我所读到的那样,规则很简单:选择最左边的叶子,这是一个运行时最低的进程.

谢谢!

mau*_*zel 10

CFS内核文档可以解释你的问题的答案,但是简单地提到它:

实际上,任务的虚拟运行时是其实际运行时间,标准化为正在运行的任务总数.

所以,vruntime实际上是规范化的.但文档没有详细说明.

它是如何实际完成的?

归一化通过min_vruntime值进行.该min_vruntime值记录在CFS runqueue(struct cfs_rq)中.该min_vruntime值是vruntimerbtree中所有任务中最小的.该值还用于跟踪所做的所有工作cfs_rq.

您可以观察在CFS enqueue_entity()代码中执行规范化的示例:

2998 static void
2999 enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
3000 {
3001         /*
3002          * Update the normalized vruntime before updating min_vruntime
3003          * through calling update_curr().
3004          */
3005         if (!(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_WAKING))
3006                 se->vruntime += cfs_rq->min_vruntime;
3007 
3008         /*
3009          * Update run-time statistics of the 'current'.
3010          */
3011         update_curr(cfs_rq);
...
3031 }
Run Code Online (Sandbox Code Playgroud)

您也可以观察到update_curr()如何vruntimemin_vruntime保持更新:

701 static void update_curr(struct cfs_rq *cfs_rq)
702 {
703         struct sched_entity *curr = cfs_rq->curr;
...
713 
714         curr->exec_start = now;
... 
719         curr->sum_exec_runtime += delta_exec;
... 
722         curr->vruntime += calc_delta_fair(delta_exec, curr);
723         update_min_vruntime(cfs_rq);
... 
733         account_cfs_rq_runtime(cfs_rq, delta_exec);
734 }
Run Code Online (Sandbox Code Playgroud)

实际更新min_vruntime发生在恰当命名的update_min_vruntime()函数中:

457 static void update_min_vruntime(struct cfs_rq *cfs_rq)
458 {
459         u64 vruntime = cfs_rq->min_vruntime;
460 
461         if (cfs_rq->curr)
462                 vruntime = cfs_rq->curr->vruntime;
463 
464         if (cfs_rq->rb_leftmost) {
465                 struct sched_entity *se = rb_entry(cfs_rq->rb_leftmost,
466                                                    struct sched_entity,
467                                                    run_node);
468 
469                 if (!cfs_rq->curr)
470                         vruntime = se->vruntime;
471                 else
472                         vruntime = min_vruntime(vruntime, se->vruntime);
473         }
474 
475         /* ensure we never gain time by being placed backwards. */
476         cfs_rq->min_vruntime = max_vruntime(cfs_rq->min_vruntime, vruntime);
...
481 }
Run Code Online (Sandbox Code Playgroud)

通过确保min_vruntime正确更新,遵循基于min_vruntime保持一致的标准化.(您可以min_vruntime通过在"normalize"或"min_vruntime"中点击来查看更多基于标准化的示例fair.c.)

因此,简单来说,所有CFS任务的vruntime值都根据当前值进行标准化min_vruntime,这可以确保在您的示例中,较新的任务vruntime将快速接近与旧任务的平衡vruntime.(我们知道这是因为文档声明min_vruntime单调增加.)

  • @mazuel半年后,我终于明白了。;)我在“ fair.c”中搜索规范化,发现[place_entity()](http://lxr.free-electrons.com/source/kernel/sched/fair.c#L3135)是min_vruntime的另一个地方用于更新se-> vruntime。所以我知道了。现在剩下的是实际逻辑。通过为任务分配min_vruntime的值来确切地更新任务的vruntime时,何时仅将min_vruntime递增,以及为什么有时将其以min_vruntime递减,如[task_waking_fair()]中所述(http://lxr.free-electrons。 com / source / kernel / sched / fair.c#L4727)?:] (2认同)