1 定时器用途
内核定时器用于在未来的指定时间点上执行某个函数;如果添加定时器时,指定的时间比系统时间要早,那么,系统将会在下一个"滴答“启动该定时器。
2 使用定时器注意事项
内核定时器基本上会在"软件中断"上下文中运行,所以定时器函数要注意以原子地运行;且定时器始终会在调度它的同一CPU上运行。另外需要遵守以下规则:
-
* 不允许访问用户空间;
-
* 不允许访问current指针;
-
* 不能执行休眠或调度。
所有处于进程上下文之外的程序都要遵守这些规则。
3 内核环境判断
内核提供两个API来判断中断上下文和原子上下文
-
#include <linux/hardirq.h>
-
int in_interrupt(); /* 如果在中断上下文,则返回非零值 */
-
int in_atomic(); /* 如果在原子上下文,则返回非零值 */
4 定时器结构
-
#include
-
struct timer_list{
-
/* 省略一些成员,只列出可由定时器代码以外的代码访问的三个成员 */
-
unsigned long expires;
-
void (*function)(unsigned long);
-
unsigned long data;
-
};
5 几个重要的定时器接口
-
#include <linux/timer.h>
-
-
void init_timer(struct timer_list *timer); /* 初始化定时器 */
-
struct timer_list TIMER_INITIALIZER(_function, _expires, _data);/* 宏初始化并指定相关成员值*/
-
-
void add_timer(struct timer_list *timer); /* 向内核添加定时器 */
-
int del_timer(struct timer_list *timer); /* 移除定时器 */
6 示例代码
-
#include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/timer.h> /* timer */
-
#include <linux/hardirq.h> /* in_interrupt(),in_atomic() */
-
-
MODULE_LICENSE("Dual BSD/GPL");
-
MODULE_AUTHOR("Kozo");
-
-
struct timer_list timer;
-
-
static inline void timer_fn(unsigned long data)
-
{
-
timer.data = jiffies;
-
timer.expires = jiffies + 2*HZ;
-
add_timer(&timer); /* 可自我注册 */
-
printk(KERN_INFO"---------------------------\n");
-
printk(KERN_INFO"jiffies_prior=%ld\n",data);
-
printk(KERN_INFO"jiffies_now =%ld\n",timer.data);
-
printk(KERN_INFO"In interrupt context: %c\n",in_interrupt()?'Y':'N');
-
printk(KERN_INFO"Is in atomic : %c\n", in_atomic()?'Y':'N');
-
}
-
-
static __init int timer_init(void)
-
{
-
init_timer(&timer);
-
timer.data = jiffies;
-
timer.function = timer_fn;
-
timer.expires = jiffies - 10; /* 验证指定的时间比系统时间早时,在下一个"滴答"执行 */
-
//timer.expires = jiffies + 2*HZ;
-
-
add_timer(&timer);
-
printk(KERN_INFO"In interrupt context: %c\n",in_interrupt()?'Y':'N');
-
printk(KERN_INFO"Is in atomic : %c\n", in_atomic()?'Y':'N');
-
-
return 0;
-
}
-
static __exit void timer_exit(void)
-
{
-
del_timer(&timer);
-
// del_timer_sync(&timer); /* 用于在SMP系统上避免竞态 */
-
}
-
module_init(timer_init);
-
module_exit(timer_exit);
7 输出结果
从输出结果可以看出,当第一次注册定时器后,确实在下一个"滴答"启动该定时器,往后便每2秒启动一次。
注:转载时请注时出自:
add358.blog.chinaunix.net
阅读(2864) | 评论(0) | 转发(0) |