1.在Linux系统中有一个重要的概念:HZ,意为节拍数,它是操作系统级的时间单位重要概念。一般大小为100(所以可以简单理解HZ为系统定义的宏),但在有些体系结构中有可能是1000或者其他,它表明了每秒钟时钟的可中断次数,时钟中断并非你想让它何时触发就能触发的,还得按着节拍来,这也进一步说明了Linux只是准实时系统,而算不上严格意义上的实时系统。
2.与HZ有关的另一个重要概念:jiffies,当前节拍计数,它是一个全局变量,且随着系统时钟不断变化(自加操作)。jiffies经常被用于定时,例如jiffies+20用来表示当前时钟后的第20个节拍数,如果HZ为100,那也就是0.2秒后的时间。jiffies的自加操作是在系统时钟中断时自动完成的,其他地方根本不需要写jiffies,而只需读取。
jiffies作为一个变量未出现归零回绕(超过无符号长整形表示的最大值时回绕),所以可能出现(jiffies+20<jiffies)的情况,这对后续的判断会产生错误,如
future=jiffies+30;
if(jiffies>future)
do_what;
上述语句在执行后的第一个判断就为1了,而不是预设定的0.3秒后触发。
解决上述回溯问题的方法是利用系统函数time_after(jiffies,futre)等,其实这个函数只是一个宏,其实现为:
#define time_after(jiffies,future) ((long)future-(long)jiffies<0) //注意这里变量已经转成带符号的了。
3. 根据上述所述的节拍数,Linux每到一个节拍就触发一次时钟中断,从而执行一次中断处理程序。显然,该中断肯定会处理的内容包括:
1)jiffies自加1
2)更新资源消耗的统计,例如当前进程又消耗了一个节拍的时间
3)执行动态定时器,之前预设的定时函数都会在该定时器中被调用
4)根据节拍情况看是否需要重新调度(其实是设置调度标志need_resched)
4. 从用户空间调用的库函数,如gettimeofday函数, ctimer结构等对应到内核空间的话,分别有函数实现的。注意,在内核实现这些函数时,需要利用锁的机制来同步。
5. 定时器是作为软中断在中断下半部被执行的。前面3.3提到的其实只是触发了定时器软中断raise_softirg(TIMER_SOFTIRQ)
6. 延迟执行的几种方法:
1)循环等待:差不多就是while语句,这里等待的条件是jiffies+某个值,这种等待非常没有效率,白白的消耗CPU
2)调度等待:也就是在等待期间可以调度其他任务,相当于进程睡眠等待
3)udelay, mdelay这样的调用,精度较高,可以是毫秒和微秒级的。
4)定时器相关:schedule_timeout,利用定时器实现延迟
5)超时+等待队列睡眠: 与2)不同之处在于,并不是其他进程执行完后唤醒该进程,而是定时器超时发生后唤醒进程。在2)中,也有查询时间超时的处理,但是在本进程中通过while(timeOK)的方式。