使用内核定时器的场景:
如果我们需要在将来的某个时间点上来执行某个动作,同时在这个时间点到来之前并不会阻塞当前进行的运行的话,我们可以通过内核定时器来实现。通过使用内核定时器,内核会在这个时间到达时(当然内核中的时间是用时钟中断数来表示的,即内核通过比较当前的jiffies中的值与我们定义的那个时钟中断数,来判断是否到时),来执行我们定义的函数,这样可以实现在一个进程中用来实现多个任务。
在内核中用 struct timer_list 来表示一个内核定时器,这个struct timer_list可以告诉内核我们什么时候执行我们的函数。
struct timer_list
{
struct list_head entry ; // 内核将内核定时器以双链表的形式组织起来;
unsigned long expires; // 用于存放函数被启动的时间;
void (*function)(unsigned long); // 用于存放我们自己定义的函数;
unsigned long data ; // 用于存放传递给自定义函数的参数;
.
.
.
}
内核定时器的静态分配及初始化
可知,内核通过 DEFINE_TIMER(timer_name, function, expries, data)宏就可以完成一个 struct timer_list定时器的定义以及初始化。
timer_name :为 struct timer_list 类型的变量名;
function : 函数名;
expries : jiffiers + n 未来的时钟中断数;
data : 传递给function函数的参数;
动态分配内核定时器;
所谓的动态分配定时器,是指进程在运行时再分配内核定时器,而不是在编译阶段进分配了内核定时器。
动态分配内核定时器的做法:
{ struct timer_list mytimer; init_timer(&mytimer); mytimer.expries = jiffies + 100; mytimer.function = myfunction; mytimer.data = mydata; }
由以上的代码可知,动态分配定时器以后,需要我们进行手动的初始化设置。
上面代码中的 init_timer()也是一个宏定义,其所做的主要工作是:
mytimer.entry.prev = NULL;
mytimer.entry.next = NULL;
当我们分配了一个内核定时器以后需要将其加入到内核中的定时器链表中,定时器才会起作用。
将一个定时器加入到内核定时器链表中的方法为:
void add_timer(struct timer_list *timer);
更改一个内核定时器中的自定义函数的方法:
setup_timer(timer, function, data ) 这也是一个宏定义,原型为:
在修改内核定时器的定时时间时,通过下面这个接口来判断内核定时器实在激活状态,还是在非激活状态:
int timer_pending( struct timer_list *timer );
如果内核定时器中处于激活状态,可以通过下面这个函数来更改内核定时器的时间
int mod_timer(struct timer_list *timer, unsigned int expries);
如果内核定时器处于非激活状态,可以通过下面这个函数来修改它的时间:
int mod_timer_pending(struct timer_list *timer, unsigned int expries )
内核定时器的删除操作:
int del_timer( struct timer_list *timer ) 用于删除一个定时器;
int del_timer_sync( struct timer_list *timer ) 也是用于删除一个定时器;
del_timer() 与 del_timer_sync()函数的不同:
del_timer_sync()函数会检测CPU上是否还有其他地方在使用这个将要被删除的内核定时器,如果有的话,等待这个内核定时器被用完然后在删除;
del_timer()还直接删除所要删除的内核定时器;
所以一般建议优先使用del_timer_sync()函数;
总结:
DEFINE_TIMER(timer_name, function, expries, data);
init_timer(struct timer_list *timer);
add_timer(struct timer_list *timer);
timer_pending(struct timer_list *timer);
mod_timer(struct timer_list *timer, unsigned int expries);
mod_timer_pending(struct timer_list *timer, unsigned int expries);
del_timer(struct timer_list *timer);
del_timer_sync(struct timer_list * timer);