了解内容
内核定时器知识
宏定义:HZ决定时钟中断的频率,通过宏CONFIG_HZ设置,范围是100~1000;
全局变量:jiffies(节拍数,内核定时器产生中断次数),系统启动时该变量初始为0,故jiffies/HZ即内核启动的秒数。
开始
定时器的使用
1、定义定时器结构体timer_list;
1
static struct timer_list my_timer;
2、结构体内容添加;
定义一个定时器时间到了的处理函数(中断触发该函数)
1
2
3
4
static void timer_func(unsigned long data)
{
printk("%s ,secs = %ld!\n",(char *)data,jiffies/HZ);
}
添加超时时间,处理函数和处理函数的传参
1
2
3
4
init_timer(&my_timer); /*初始化my_timer的部分内部成员*/
my_timer.expires = jiffies + 5*HZ; //当前时间(jiffies)的后5秒(5*HZ)
my_timer.function = timer_func; //指定定时器处理函数
my_timer.data = (unsigned long)123; //设定定时器处理函数的传参,甚至可传字符串
3、激活定时器;
1
2
3
4
5
6
//方式一:添加即启动定时器
add_timer(&my_timer);
//方式二:改变超时时间
//如果目前没超时,就会更新时间;
//如果目前已触发超时,就相当于更新时间并再次启动一次
mod_timer(&my_timer,jiffies + 10*HZ);
例程
驱动例程
timer_demo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("jerry");
static struct timer_list my_timer;
static void timer_func(unsigned long data)
{
printk("%s ,secs = %ld!\n",(char *)data,jiffies/HZ);
//方式二:改变超时时间
//如果目前没超时,就会更新时间;
//如果目前已触发超时,就相当于更新时间并再次启动一次
mod_timer(&my_timer,jiffies + 5*HZ);
}
static int __init demo_init(void){
init_timer(&my_timer); /*初始化my_timer的部分内部成员*/
my_timer.expires = jiffies + 2*HZ; //当前时间(jiffies)的后2秒(2*HZ)
my_timer.function = timer_func; //指定定时器处理函数
my_timer.data = (unsigned long)"haha"; //设定定时器处理函数的传参,这里指针强转
//方式一:添加即启动定时器
add_timer(&my_timer);
printk(KERN_EMERG "mytimer start!\n");
return 0;
}
static void __exit demo_exit(void){
printk(KERN_EMERG "mytimer exit!\n");
del_timer(&my_timer);
return;
}
module_init(demo_init);
module_exit(demo_exit);
测试结果
编写简单Makefile:参考这里
编译生成模块后,拷贝到开发板中:
-
加载模块后第一次2s触发定时器中断,后面每5s触发一次。