调度器30—调度相关结构体—struct sched_entity
一、struct sched_entity
1. se->sum_exec_runtime
表示实际running的时间,不包括runnable时间。
(1) sum_exec_runtime 的更新逻辑
void set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
...
update_stats_curr_start(cfs_rq, se);
/* 选中当前se去运行 */
cfs_rq->curr = se;
...
/* 新的一次运行开始的时候才将sum值赋值给prev_sum */
se->prev_sum_exec_runtime = se->sum_exec_runtime;
}
static inline void update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
{
/* We are starting a new run period:*/
se->exec_start = rq_clock_task(rq_of(cfs_rq)); //return rq->clock_task;
}
static void update_curr(struct cfs_rq *cfs_rq)
{
struct sched_entity *curr = cfs_rq->curr;
u64 now = rq_clock_task(rq_of(cfs_rq));
u64 delta_exec;
...
/* 在核间迁移时,调整的是 exec_start, sum_exec_runtime 是单调累加的,核间迁移也不影响 */
delta_exec = now - curr->exec_start;
...
curr->exec_start = now;
...
/* 更新任务累计的运行时间 */
curr->sum_exec_runtime += delta_exec;
/* 更新 se 的虚拟时间 */
curr->vruntime += calc_delta_fair(delta_exec, curr);
update_min_vruntime(cfs_rq);
...
}
(2) 实验
# echo lock > /sys/power/wake_lock
//搞5个死循环,掐秒表10s
# let i=0; while true; do let i=i+1; done &
//5个死循环绑定cpu1
# taskset -p 01 24961
10测试前:
# for P in 24937 24940 24946 24955 24961; do cat /proc/$P/sched | grep se.sum_exec_runtime; done;
se.sum_exec_runtime : 59548.030554
se.sum_exec_runtime : 43598.199964
se.sum_exec_runtime : 38325.025722
se.sum_exec_runtime : 31508.426646
se.sum_exec_runtime : 28923.228260
10测试后:
# for P in 24937 24940 24946 24955 24961; do cat /proc/$P/sched | grep se.sum_exec_runtime; done;
se.sum_exec_runtime : 61571.478979
se.sum_exec_runtime : 45617.150613
se.sum_exec_runtime : 40347.151159
se.sum_exec_runtime : 33529.815536
se.sum_exec_runtime : 30944.450859
10s后 10s前 delta
61571.47898 59548.03055 2023.448425
45617.15061 43598.19996 2018.950649
40347.15116 38325.02572 2022.125437
33529.81554 31508.42665 2021.38889
30944.45086 28923.22826 2021.222599
可以看到,统计到的每个进程的运行时间是2s,而不是10s,验证了的确是运行时间不包括runnable时间。
2. se->vruntime
vruntime 主要在 update_curr() 中进行更新,每次都是加上执行时间在自己权重上映射得到的虚拟时间。在任务迁移时,迁移的是 se->vruntime -= cfs_rq->min_vruntime, 迁移到新CPU后恢复的是 se->vruntime += cfs_rq->min_vruntime。在任务唤醒时,或唤醒的是休眠的任务则会进行虚拟时间补偿,若唤醒的是新fork出来的任务,则会进行虚拟时间惩罚,见place_entity()。
除此之外,虚拟时间没有其它额外更新路径!
posted on 2022-07-23 20:08 Hello-World3 阅读(445) 评论(0) 编辑 收藏 举报