8. 时钟中断中的调度 时钟中断对于调度系统来说就是一种驱动力。在时钟中断中,调度相关的一些时间计数量会被更新。同时会检查一下目前运行的进程运行时间是不是超过了一个slice,如果超过了这个间隔,就会设置重新调度标记。会在schedule函数中完成调度并完成进程切换。如果没有小于这个slice量,那就不会触发重新调度。为什么这么做呢?因为时钟中断触发频率是很高的,每秒有1000个tick,如果一个tick就重新调度一次,那么cpu将忙于进程切换,将大量的cpu白白浪费掉了,所以进程切换的频率必须掌握一个度。
看到这里,我们应该明白时钟中断对于调度的重要性了,如果不是有时钟中断,那么进程切换就都得仰仗进程自己自觉地调度schedule函数了,这是多么不靠谱的事情。这就好比别人占着的茅坑,即便他没有在拉屎,也不知道什么时候能让出来,常言道占着茅坑不拉屎嘛!
/* * Preempt the current task with a newly woken task if needed: */ static void check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) { unsigned long ideal_runtime, delta_exec; ideal_runtime = sched_slice(cfs_rq, curr); delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; if (delta_exec > ideal_runtime) { resched_task(rq_of(cfs_rq)->curr); /* * The current task ran long enough, ensure it doesn't get * re-elected due to buddy favours. */ clear_buddies(cfs_rq, curr); } } |
上面的过程比较简单,需要主要的是ideal_runtime = sched_slice(cfs_rq, curr)这个时间是如何计算出来的呢?大概的公式就是4msec * 进程数目 *进程load占runqueue总共的load的比重。目测一下,一个进程被调度一次的持续运行的时间(ideal time)也就是4msec左右。
/* * The idea is to set a period in which each task runs once. * * When there are too many tasks (sysctl_sched_nr_latency) we have to stretch * this period because otherwise the slices get too small. * * p = (nr <= nl) ? l : l*nr/nl */ static u64 __sched_period(unsigned long nr_running) { u64 period = sysctl_sched_latency; unsigned long nr_latency = sched_nr_latency; if (unlikely(nr_running > nr_latency)) { period = sysctl_sched_min_granularity; period *= nr_running; } return period; } |
阅读(3085) | 评论(0) | 转发(1) |