定时器,有时也称为动态定时器或内核定时器,是管理内核时间的基础
内核经常要推迟执行一些代码,如下半部机制就是为了将工作推后执行
时钟中断由系统的定时硬件以周期性的时间间隔产生,这个间隔(即频率)由内核根据HZ来确定
每当时钟中断发生时,全局变量jiffies(unsigned long)就加1,因此jiffies记录了自linux启动后时钟中断发生的次数。
内核定时器用于控制某个函数(定时器处理函数)在未来的某个特定时间执行。
内核定时器注册的处理函数只执行一次--不是循环执行的。(定时器并不周期运行,它在超时后就自行销毁,动态
定时器不断地创建和销毁,而且它的运行次数也不受限制)
定时器的使用只须执行一些初始化工作,设置一个超时时间,指定超时发生后执行的函数,然后激活定时器就可以了
1. 定时器结构timer_list
include/linux/timer.h
struct timer_list {
struct list_head entry;//定时器链表的入口
unsigned long expires;//定时器到期时间
struct tvec_base *base;
void (*function)(unsigned long);//定时器处理函数
unsigned long data;//传给定时器处理函数的长整形参数
int slack;
...
};
2. 定时器的使用
1)定义一个定时器结构
struct timer_list timer;
2)初始化定时器
有很多接口函数可以初始化定时器
init_timer(struct timer_list* timer);
TIMER_INITIALIZER(_function, _expires, _data);
DEFINE_TIMER(_name, _function, _expires, _data);
通常可以这样初始化定时器并赋值func,data
setup_timer(&timer, gpio_keys_timer, (unsigned long)data);
定时器处理函数
static void gpio_keys_timer(unsigned long data)
{
schedule_work(&work);
}
3)增加定时器,并激活定时器
void add_timer(struct timer_list* timer);
注册内核定时器,并将定时器加入到内核动态定时器链表中
4)删除定时器
int del_timer(struct timer_list *timer);
del_timer_sync(struct timer_list *timer);
del_timer_sync()是del_timer()的同步版,在删除一个定时器时需等待其被处理完(不能在中断上下文中使用)
5)修改定时器的expire,并启动
int mod_timer(struct timer_list *timer, unsigned long expires);
mod_timer(&timer, jiffies + msecs_to_jiffies(50));//未考虑jiffies溢出问题
msecs_to_jiffies()用于将ms转换成jiffies
/********************************************************/
内核定时器例子
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/fs.h>
#define TIMER_MAJOR 234
#define DEVICE_NAME "timer_test"
/**1. 定义timer结构*/
struct timer_list timer;
static void func_timer(unsigned long data)
{
/**4. 修改定时器的超时参数并重启*/
mod_timer(&timer, jiffies + HZ);
printk("current jiffies is %ld\n", jiffies);
}
struct file_operations timer_ops = {
.owner = THIS_MODULE,
};
static int __init timer_init(void)
{
register_chrdev(TIMER_MAJOR, DEVICE_NAME, &timer_ops);
/**2. 初始化定时器*/
setup_timer(&timer, func_timer, 0);
#if 0
init_timer(&timer);
timer.data = 0;
timer.expires = jiffies + HZ;
timer.function = func_timer;
#endif
/**3. 添加激活计时器*/
add_timer(&timer);
printk("timer_init\n");
return 0;
}
static void __exit timer_exit(void)
{
/**4. 删除定时器*/
del_timer(&timer);
unregister_chrdev(TIMER_MAJOR, DEVICE_NAME);
}
module_init(timer_init);
module_exit(timer_exit);
MODULE_LICENSE("GPL");
/********************************************************/
# insmod timer_test.ko
timer_init
timer_init
current jiffies is 220614
current jiffies is 220614
current jiffies is 220714
current jiffies is 220714