linux驱动之内核定时器驱动设计
}
}
timer->expires = expires;
internal_add_timer(base, timer);
out_unlock:
spin_unlock_irqrestore(&base->lock, flags);
return ret;
}
static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
{
unsigned long expires = timer->expires;
unsigned long idx = expires - base->timer_jiffies;
struct list_head *vec;
if (idx < TVR_SIZE) {
int i = expires & TVR_MASK;
vec = base->tv1.vec + i;
} else if (idx < 1 < (TVR_BITS + TVN_BITS)) {
int i = (expires >> TVR_BITS) & TVN_MASK;
vec = base->tv2.vec + i;
} else if (idx < 1 < (TVR_BITS + 2 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
vec = base->tv3.vec + i;
} else if (idx < 1 < (TVR_BITS + 3 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
vec = base->tv4.vec + i;
} else if ((signed long) idx < 0) {
/*
* Can happen if you add a timer with expires == jiffies,
* or you set a timer to go off in the past
*/
vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
} else {
int i;
/* If the timeout is larger than 0xffffffff on 64-bit
* architectures then we use the maximum timeout:
*/
if (idx > 0xffffffffUL) {
idx = 0xffffffffUL;
expires = idx + base->timer_jiffies;
}
i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
vec = base->tv5.vec + i;
}
/*
* Timers are FIFO:
*/
/*添加到链表的最后,这说明mod_timer实现了重新注册一个定时器的操作*/
list_add_tail(&timer->entry, vec);
}
从上面的分析可以看出,mod_timer的实现过程比较复杂,但是基本上说明了mod_timer函数重新注册定时器的操作过程。
一般而言定时器的基本操作主要是上面的几个函数。
我的基于内核定时器的驱动函数如下,参考了宋宝华的Linux设备驱动开发详解(第二版)。
驱动程序:
#include #include #include #include #include #include #include #include #include #include #include /*采用宏定义设置设备的主设备号*/ #define SECOND_MAJOR 0 /*静态的分别保存静态主设备号的变量*/ static int second_major = SECOND_MAJOR; /*设备结构体,通常在设备中包含需要的设备,比如字符、块等类型*/ struct second_dev{ /*添加设备类型, 我认为可以采用一个联合体, 包含块设备或者字符设备,类似inode的实现方法, 这样可以提高结构体的通用性 */ struct cdev cdev; /*原子变量,用来统计*/ atomic_t counter; /*添加内核定时器结构体变量*/ struct timer_list s_timer; /*用于动态创建设备文件的设备类*/ struct class *myclass; }; /*结构体指针或者采用全局变量直接定义结构都可以*/ struct second_dev *second_devp; /*如果定时时间到了,定时器的处理函数*/ static void second_timer_handler(unsigned long arg) { /* 修改定时器中的到期时间,增加时间为1s, 需要注意的是mod_timer函数是重新注册定时器到内核 而不管定时器是否被运行过 */ mod_timer(&second_devp->s_timer,jiffies + HZ); /*原子变量的增加*/ atomic_inc(&second_devp->counter); /*输出jiffies值*/ printk(KERN_NOTICE "Current jiffies is %d",jiffies); } /*open函数实现*/ static int second_open(struct inode *inode,struct file *filp) { /*初始化定义的内核定时器*/ init_timer(&second_devp->s_timer); /*指定内核定时器的处理函数是上面定义好的函数*/ second_devp->s_timer.function = second_timer_handler; /*指定定时间隔是1s*/ second_devp->s_timer.expires = jiffies + HZ; /*将定时器添加到内核*/ add_timer(&second_devp->s_timer); /*同时设备相关的统计值为0*/ atomic_set(&second_devp->counter,0); return 0; } /*release函数的实现*/ static int second_release(struct inode *inode,struct file *filp) { /*如果没有到时间
linux驱动内核定时器驱 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
