定时器
1. 指定timeout时刻执行超时处理函数
2. 一旦到期,内核会删除该定时器,超时处理函数只会执行一次
3. 定时器基于软中断实现,在定时器的处理函数中,不允许休眠
数据结构
头文件 #include <linux/timer.h>
expires: 不是超时时间,而是将来的某个时刻点 即 jiffies + timeout
代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
MODULE_DESCRIPTION("Frocheng: Driver for DEMO!");
MODULE_AUTHOR("Frodo Cheng");
MODULE_LICENSE("GPL");
MODULE_VERSION("V0.0.1");
#define HELLO_TIMEOUT_SEC (1ULL * HZ)
static struct timer_list hello_timer;
static char* name = "HelloTimer";
static void timer_handle_cb(struct timer_list * pt)
{
printk("===[frocheng]===[%s]===[%s]===[%d]===[%s]===\n",__FILE__, __func__, __LINE__, name);
mod_timer(&hello_timer, jiffies + 2 * HELLO_TIMEOUT_SEC);
}
static int __init hello_init(void)
{
printk("===[frocheng]===[%s]===[%s]===[%d]===[Hello !]===\n",__FILE__, __func__, __LINE__);
hello_timer.expires = jiffies + 2 * HELLO_TIMEOUT_SEC;
init_timer_key(&hello_timer, timer_handle_cb, 0, name, NULL);
add_timer(&hello_timer);
return 0;
}
static void __exit hello_exit(void)
{
del_timer(&hello_timer);
printk("===[frocheng]===[%s]===[%s]===[%d]===[Bye bye...]===\n",__FILE__, __func__, __LINE__);
}
module_init(hello_init);
module_exit(hello_exit);
由于超时处理函数中,有一个prink的操作,便不试验了,把这个printk的操作,放到工作队列中去处理。
代码,工作队列
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
MODULE_DESCRIPTION("Frocheng: Driver for DEMO!");
MODULE_AUTHOR("Frodo Cheng");
MODULE_LICENSE("GPL");
MODULE_VERSION("V0.0.1");
#define HELLO_TIMEOUT_SEC (1ULL * HZ)
static struct timer_list hello_timer;
static struct work_struct w;
static char* name = "HelloTimer";
static void wq_handle_cb(struct work_struct * w)
{
printk("===[frocheng]===[%s]===[%s]===[%d]===[%s]===\n",__FILE__, __func__, __LINE__, name);
}
static void timer_handle_cb(struct timer_list * pt)
{
mod_timer(&hello_timer, jiffies + 2 * HELLO_TIMEOUT_SEC);
schedule_work(&w);
}
static int __init hello_init(void)
{
printk("===[frocheng]===[%s]===[%s]===[%d]===[Hello !]===\n",__FILE__, __func__, __LINE__);
INIT_WORK(&w, wq_handle_cb);
hello_timer.expires = jiffies + 2 * HELLO_TIMEOUT_SEC;
init_timer_key(&hello_timer, timer_handle_cb, 0, name, NULL);
add_timer(&hello_timer);
return 0;
}
static void __exit hello_exit(void)
{
del_timer(&hello_timer);
printk("===[frocheng]===[%s]===[%s]===[%d]===[Bye bye...]===\n",__FILE__, __func__, __LINE__);
}
module_init(hello_init);
module_exit(hello_exit);
结果
注意:
由于是 ONE SHOT 方式的timer,如果需要循环的执行,那么就需要在 callback 中
1. 不断的更新 expires 域的值
2. 不断的add_timer
3. 为了安全 在 1,2之前先 del_timer(),因为,如果执行到了处理函数,内核已经执行了 del_timer(),但是即便如此,此时 del_timer() 也无影响。
但是以上三步的执行路径并不具备原子性,所以用一个 mod_timer(),一个原子性操作的接口,完成以上三步。