定时器,有时也称为动态定时器或内核定时器,是管理内核时间的基础。内核经常要推后执行某些代码,比如下半部机制就是为了将工作推后执行。我们需要一种工具,使工作能够在指定时间点上执行,正好在希望的时间点上,内核定时器正是这样一种工具。
定时器使用简单,只须执行一些初始化工作,设置一个超时时间,指定超时发生后执行的函数,然后激活定时器就可以了。注意,定时器并不周期运行,它在超时后就自行销毁,这就是这种定时器被称为动态定时器的原因。动态定时器不断地创建和销毁,而且它的运行次数也不受限制。
定时器由结构timer_list表示:
在<timer.h(include/linux)>中
<span style="font-size:14px;">2.struct timer_list {
3. struct list_head entry; //定时器链表的入口
4. unsigned long expires; //定时器超时时的节拍数
5.
6. void (*function)(unsigned long ); //定时器处理函数
7. unsigned long data; //传给定时器处理函数的长整型参数
8.
9. struct tvec_t_base_s *base; //定时器内部值,用户不要使用
}</span>
内核提供了一组与定时器相关的接口用来简化管理定时器的操作。所有这些接口都声明在<linux/timer.h>中,大多数接口在<kernel/timer.c>中的到实现。
创建定时器首先要先定义它,然后通过一个辅助函数初始化定时器数据结构的内部值,初始化必须在使用其他定时器管理函数之前完成:
1.struct timer_list my_timer;
2.init_timer(&my_timer); // 初始化定时器
3.my_timer.expires = jiffies + delay;// delay这个值一般为seconds*HZ
4.my_timer.data = 0; // 传递给function的参数
5.my_timer.function = my_function;
6.add_timer(&my_timer); //最后,激活定时器
定时器的使用中,下面3个概念非常重要:
- HZ
- jiffies
- 时间中断处理程序
HZ
Linux核心每隔固定周期会发出timer interrupt (IRQ 0),HZ是用来定义每一秒有几次timer interrupts。举例来说,HZ为1000,代表每秒有1000次timer interrupts。
其中HZ可设定100、250、300或1000。
Tick
Tick是HZ的倒数,意即timer interrupt每发生一次中断的时间。如HZ为100时,tick为10ms(millisecond)。
Jiffies
Jiffies为Linux核心变数(32位元变数,unsigned long),它被用来纪录系统自开机以来,已经过多少的tick。每发生一次timer interrupt,Jiffies变数会被加1。所以一个jiffies的精度是一个Tick = (1/HZ)s,从上面看出其精度通常在ms级内。
所以,timer.expires - jiffies相减的结果就是设置超时的时间间隔。