参考:《linux设备驱动开发详解》宋宝华-人民邮电出版社、itop4412驱动开发视频教程
内核时钟基础知识:
HZ:(系统时钟通过CONFIG_HZ来设置,范围是100-1000;HZ决定时钟中断发生的频率)
内核的全局变量jiffies:(记录内核自启动来的节拍数,内核之启动以来,产生的中断数)
jiffies/HZ :内核自启动以来的秒数
使用 vi config_for_linux_scp_elite 命令,在配置文件中查看,搜索CONFIG_HZ可以获知HZ时钟频率。
jiffies参数的头文件 #include "linux/jiffies.h"
内核定时器编程
1.timer_list结构体
在 Linux 内核中,timer_list 结构体的一个实例对应一个定时器
struct timer_list {
struct list_head entry;
unsigned long expires;
struct tvec_base *base;
void (*function)(unsigned long);
unsigned long data;
...
};
timer_list 结构体内的参数:
- struct list_head entry 双向链表。
- unsigned long expires;超时时间。记录什么时候产生时钟中断。
- struct tvec_base *base;管理时钟的结构体
- void (*function)(unsigned long);时钟中断产生之后的动作
- unsigned long data;传递的参数
2.初始化定时器
init_timer(timer)
上述 init_timer()函数初始化 timer_list 的 entry 的 next 为 NULL,并给 base 指针赋
值。
TIMER_INITIALIZER(_function, _expires, _data)宏用于赋值定时器结构体的function、expires、data 和 base 成员
setup_timer(timer, fn, data)
setup_timer也用于初始化定时器,同时赋值其成员
参数:
- struct timer_list * timer
- void (*function)(unsigned long)
- unsigned long data
3.增加定时器
extern void add_timer(struct timer_list *timer);
4.删除定时器
extern int del_timer(struct timer_list * timer);
5.修改定时器的expires
extern int mod_timer(struct timer_list *timer, unsigned long expires);
上述函数用于修改定时器的到期时间,在新的被传入的 expires 到来后才会执行定时器函数。
mod_timer = del_timer(timer);timer->expires = expires; add_timer(timer);
简单驱动代码
#include "linux/module.h"
#include "linux/timer.h"
#include "linux/jiffies.h"
struct timer_list demo_timer;
static void time_func(unsigned long data)
{
printk("%s ,secs = %ld!\n",(char *)data,jiffies/HZ);
mod_timer(&demo_timer,jiffies + 5*HZ);
}
static int __init mytimer_init(void)
{
printk("mytimer_init!\n");
setup_timer(&demo_timer,time_func,(unsigned long) "demo_timer!");
demo_timer.expires = jiffies + 1*HZ;
add_timer(&demo_timer);
return 0;
}
static void __exit mytimer_exit(void)
{
printk("mytimer_exit!\n");
del_timer(&demo_timer);
}
module_init(mytimer_init);
module_exit(mytimer_exit);
MODULE_LICENSE("Dual BSD/GPL");