在sched_fair.c
中它有:
unsigned int sysctl_sched_latency = 5000000ULL //5m
unsigned int sysctl_sched_min_granularity = 1000000ULL //1ms
据我所知,Linux公平时间片根据nr_running和这个公平任务的相对权重而有所不同,但通过代码学习,我发现主要思想是将时间片保持1到5毫秒。如果我理解错了,请纠正我。我一定是错的,但我无法弄清楚如何!
同样知道HZ,或每秒的系统滴答数,或每秒钟的定时器中断次数,对于arm机器(以及大多数非台式机器)来说通常为200或100,这给了我们5到10毫秒的滴答率。
每次在set_next_entity()
中启动rq-> hrtick_timer时,每次安排公平任务运行,并在超时回调函数resched_task()
中调用hrtick()
时,都会启动Timeslice。此计时器只是在每个刻度timer_tick()
... run_local_timer()
上由计时器irq处理程序处理的排队计时器之一。似乎没有其他隐藏的秘密。
那么我们如何才能得到一个短于5毫秒的时间片?请帮我理解这个。非常感谢你!
答案 0 :(得分:2)
如Robert Love的Linux内核开发中所述,缩短时间片的唯一方法是增加正在运行的进程数(或者优先级低于其他进程的进程)。
运行过程中的数量越来越多,需要缩短时间片以确保适当的目标延迟(但时间片的最小粒度更低)。但是不能保证在给定的时间片中过程会被抢占。那是因为时间计算是由计时器中断驱动的。
增加HZ的值会使定时器中断更频繁地发生,这使得时间会计更加珍贵,因此可能更频繁地重新安排。
vruntime
变量存储进程的虚拟运行时,它是由可运行进程数量标准化的实际运行时。在理想的多任务系统中,所有过程的运行时间都是相同的 - 所有任务都将获得相同,公平的处理器份额。
通常,时间片是目标延迟除以正在运行的进程数。但是当运行进程的数量接近无穷大时,时间片接近0.因为这最终会导致不可接受的转换成本,CFS会在分配给每个进程的时间片上设置一个底限。此层称为最小粒度。因此,时间片是sysctl_sched_latency
和sysctl_sched_granularity
之间的值。 (见sched_timeslice()
)
vruntime
变量由update_curr()
管理。系统计时器定期调用update_curr()
,并且只要进程变为可运行或阻塞,就会变得不可用。
要在任务之间取消抢占,hrtick()
会在每个定时器中断上调用task_tick_fair()
,而中断则会调用entity_tick()
。 entity_tick()
调用update_curr()
来更新流程vruntime
,然后调用check_preempt_tick()
。 check_preempt_tick()
检查当前运行时是否大于理想运行时(timeslice),如果是,则调用resched_task()
,设置TIF_NEED_RESCHED
标志。
设置TIF_NEED_RESCHED
后,会在最近的情况下调用schedule()
。
因此,随着HZ
值的增加,定时器中断会更频繁地发生,从而导致更多宝贵的时间计算并允许调度程序更频繁地重新安排任务。