Linux 内核定时器

时间:2022-01-28 23:32:10

定时器,有时也称为动态定时器或内核定时器,是管理内核时间的基础
内核经常要推迟执行一些代码,如下半部机制就是为了将工作推后执行
时钟中断由系统的定时硬件以周期性的时间间隔产生,这个间隔(即频率)由内核根据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