【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】
Linux 内核所提供的用于操作定时器的数据结构和函数(位于 <linux/timer.h>)如下
struct timer_list { /*
* All fields that change during normal runtime grouped to the
* same cacheline
*/
struct list_head entry; /* 定时器列表 */
unsigned long expires; /* 期望定时器执行的jiffies值 */
struct tvec_base *base;
void (*function)(unsigned long);/* 定时器处理函数 */
unsigned long data; /* 作为参数被传入定时器处理函数 */
int slack;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
使用定时器必须初始化,使用函数
void init_timer(struct timer_list * timer);然后还需为定时器结构成员expires、function、data(需要的话)赋值。
使用如下函数注册定时器:
void add_timer(struct timer_list * timer);这样定时器将在expires之后执行函数function,不过此时只能执行一次,如果想在之后每个expires时间都执行function函数的话,需要在function函数里面修改定时器expires的值。使用如下函数修改:
int mod_timer(struct timer_list *timer, unsigned long expires);在定时器处理函数中,在做完相应的工作后,往往会延后 expires 并将定时器再次添加到内核定时器链表,以便定时器能再次被触发。
一个示例如下:
#include <linux/module.h>#include <linux/init.h>
#include <linux/version.h>
#include <linux/timer.h>
#include <linux/delay.h>
struct timer_list sln_timer;
void sln_timer_do(unsigned long l)
{
mod_timer(&sln_timer, jiffies + HZ);//HZ为1秒,在此时间之后继续执行
printk(KERN_ALERT"jiffies: %ld\n", jiffies);//简单打印jiffies的值
}
void sln_timer_set(void)
{
init_timer(&sln_timer);//初始化定时器
sln_timer.expires = jiffies + HZ; //1s后执行
sln_timer.function = sln_timer_do; //执行函数
add_timer(&sln_timer); //向内核注册定时器
}
static int __init sln_init(void)
{
printk(KERN_ALERT"===%s===\n", __func__);
sln_timer_set();
return 0;
}
static void __exit sln_exit(void)
{
printk(KERN_ALERT"===%s===\n", __func__);
del_timer(&sln_timer);//删除定时器
}
module_init(sln_init);
module_exit(sln_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("sln");
像定时器这种周期性的任务还可以使用延时工作队列来实现。
给一个示例:
#include <linux/module.h>#include <linux/init.h>
#include <linux/version.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
static struct workqueue_struct *sln_wq = NULL;
static struct delayed_work sln_dwq;
static void sln_do(struct work_struct *ws)
{
queue_delayed_work(sln_wq, &sln_dwq, 1000);
printk(KERN_ALERT"jiffies: %ld\n", jiffies);
}
static int __init sln_init(void)
{
printk(KERN_ALERT"===%s===\n", __func__);
sln_wq = create_workqueue("sln_work_queue");
INIT_DELAYED_WORK(&sln_dwq, sln_do);
queue_delayed_work(sln_wq, &sln_dwq, 0);
return 0;
}
static void __exit sln_exit(void)
{
printk(KERN_ALERT"===%s===\n", __func__);
cancel_delayed_work(&sln_dwq);
flush_workqueue(sln_wq);
destroy_workqueue(sln_wq);
}
module_init(sln_init);
module_exit(sln_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("allen");