完全公平调度程序 (CFS):长 运行 进程的 vruntime
Completely Fair Scheduler (CFS): vruntime of long running processes
如果 vruntime 自创建进程以来就被计算在内,那么如果这样的进程与新创建的处理器绑定进程竞争(比方说比天更年轻),那么为什么这样的进程甚至会获得处理器?
正如我所读,规则很简单:选择最左边的叶子,这是运行时间最短的进程。
谢谢!
kernel documentation for CFS 掩盖了您问题的答案,但简要提及:
In practice, the virtual runtime of a task
is its actual runtime normalized to the total number of running tasks.
所以,vruntime
实际上是标准化的。但是文档没有详细说明。
实际是怎么做到的?
标准化是通过 min_vruntime
值进行的。此 min_vruntime
值记录在 CFS 运行队列 (struct cfs_rq
) 中。 min_vruntime
值是 rbtree 中所有任务中最小的 vruntime
。该值还用于跟踪 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 }
您还可以在 update_curr()
中观察 vruntime
和 min_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 }
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 }
通过确保 min_vruntime
得到正确更新,基于 min_vruntime
的规范化保持一致。 (您可以通过在 fair.c
中查找 "normalize" 或 "min_vruntime" 来查看更多基于 min_vruntime
规范化的示例。)
所以简单来说,所有 CFS 任务的 vruntime
值都基于当前 min_vruntime
进行标准化,这确保在您的示例中,较新任务的 vruntime
将快速接近与旧任务的平衡 vruntime
。 (我们知道这一点是因为文档指出 min_vruntime
是单调递增的。)
如果 vruntime 自创建进程以来就被计算在内,那么如果这样的进程与新创建的处理器绑定进程竞争(比方说比天更年轻),那么为什么这样的进程甚至会获得处理器?
正如我所读,规则很简单:选择最左边的叶子,这是运行时间最短的进程。
谢谢!
kernel documentation for CFS 掩盖了您问题的答案,但简要提及:
In practice, the virtual runtime of a task is its actual runtime normalized to the total number of running tasks.
所以,vruntime
实际上是标准化的。但是文档没有详细说明。
实际是怎么做到的?
标准化是通过 min_vruntime
值进行的。此 min_vruntime
值记录在 CFS 运行队列 (struct cfs_rq
) 中。 min_vruntime
值是 rbtree 中所有任务中最小的 vruntime
。该值还用于跟踪 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 }
您还可以在 update_curr()
中观察 vruntime
和 min_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 }
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 }
通过确保 min_vruntime
得到正确更新,基于 min_vruntime
的规范化保持一致。 (您可以通过在 fair.c
中查找 "normalize" 或 "min_vruntime" 来查看更多基于 min_vruntime
规范化的示例。)
所以简单来说,所有 CFS 任务的 vruntime
值都基于当前 min_vruntime
进行标准化,这确保在您的示例中,较新任务的 vruntime
将快速接近与旧任务的平衡 vruntime
。 (我们知道这一点是因为文档指出 min_vruntime
是单调递增的。)