在Linux单处理器系统中,定时器中断与系统处于内核模式还是用户模式无关?
当系统处于内核模式时,定时器中断是否有任何不同的行为?
答案 0 :(得分:6)
简单的答案是硬件时钟中断服务程序的执行和动态定时器处理程序的调度都不受系统在硬件时钟中断之前所处的模式的影响。原因是时钟定时器中断是一个立即服务的硬件中断,无论执行是在内核还是用户上下文中(假设启用了定时器中断),以及时钟定时器的中断服务程序中断本身会引发运行动态定时器处理程序的软件中断。
警告:1)我实际上并没有凭经验证明这一点。 2)这不适用于无滴答内核或高阶定时器。Linux内核代码使用“计时器”一词来表示几个不同的东西:
硬件时钟或滴答计时器
在使用硬件时钟提供“滴答”的系统上,时钟定时器中断是依赖于体系结构的硬件中断。例如,在arch/powerpc/kernel/head_booke.h中查找“timer_interrupt”,然后在arch/powerpc/kernel/time.c中查看中断服务例程(ISR)timer_interrupt
实现。无论当前执行上下文如何,当发生定时器中断时,该ISR立即执行。此硬件中断与其他硬件中断不同,因为当它返回时,处理不会返回到先前的上下文。而是输入调度程序。
对于设置为每秒产生1000个时钟中断的系统,有可能在其他中断服务时屏蔽时钟中断。这通常被称为“丢失的滴答”问题。如果不补偿丢失的滴答声,加载的系统可能会减慢时间感。在某些体系结构中,内核通过使用更细粒度的硬件增量计数器来补偿丢失的滴答,其计数器的值在每个时钟定时器中断时被读取和记录。通过将当前滴答的增量计数器值与前一个滴答的增量计数器值进行比较,内核可以判断滴答是否已丢失。
软件定时器
动态定时器处理程序(您使用linux/timer.h
设置的类型)已经过期的动态定时器列表在时钟定时器中断结束时设置,然后返回。序列是(大约):
[arch dependent]:timer_interrupt( )
kernel/time/tick-common.c:tick_handle_periodic( )
kernel/time/tick-common.c:tick_periodic( )
kernel/timer.c:update_process_times( )
kernel/timer.c:run_local_timers( )
kernel/softirq.c:raise_softirq(TIMER_SOFTIRQ)
我省略了将timer_interrupt
的处理程序设置为tick_handle_periodic
的初始化,以及TIMER_SOFTIRQ
的处理程序。
对raise_softirq(TIMER_SOFTIRQ)
的调用会生成一个立即处理的软件中断。中断的ISR运行动态定时器队列。定时器处理程序在softirq上下文中运行,并启用硬件中断。当ISR返回时,调用调度程序。这意味着如果设置了很多计时器,那么运行队列中接下来的任何进程都将被延迟。
如果丢失了滴答,那么定时器处理程序的执行可能会被延迟,但是,延迟不依赖于在运行时钟定时器中断之前的执行事件。
关于动态计时器准确度的注意事项
“......内核无法确保定时器功能在其到期时间内正常运行。它只能确保它们在适当的时间执行,或者在延迟达到几百毫秒之后执行。” 了解Linux内核,Bovet和Cesati,第3版,O'reilly。
因此,如果您需要更好的计时器精度,则需要使用高位计时器。