在Linux设备驱动编程中,可以利用Linux内核中提供的一组函数和数据结构来完成定时出发或完成某周期性的事物。这组函数和
数据结构使得驱动工程师多数情况下不用关心具体的软件定时器究竟对应着怎样的内核和硬件行为。
Linux内核提供的用于操作的定时器的数据结构和函数如下:
1)timer_list 结构体
timer_list结构体的一个实例对应一个定时器,代码如下:
- struct timer_list{
- struct list_head entry;//定时器列表
- unsigned long expires;//定时器到期时间
- void (*function)(unsigned long);//定时器处理函数
- unsigned long data;//作为参数被传入定时器处理函数
- struct timer_base_s *base;
- };
当定时器期满后,function()成员被执行,而data成员是传入其中的参数,expire则是定时器到期时间。
struct timer_list my_timer;//定义一个定时器my_timer
2)初始化定时器
void init_timer(struct timer_list *timer);//函数init_timer()主要设置该内核定时器归属系统中哪一个处理,并初始化内核定时器链表指针的next域为NULL
TIMER_INITIALIZER(_function,_expires,_data)宏用于赋值定时器结构体的function、expires、data和base成员,宏的定义如下:
- #define TIMER_INITIALIZER(_function, _expires, _data) { \
- .function = (_function), \
- .expires = (_expires), \
- .data = (_data), \
- .base = &_init_timer_base, \
- }
DEFINE_TIMER(_name, _function, _expires, _data)宏是定义并初始化定时器成员的快捷方式,这个宏的定义如下所示:
#define DEFINE_TIMER(_name, _function, _expires, _data) \
struct timer_list _name = \
TIMER_INITIALIZER(_function, _expires, _data)
此外,setup_timer()也可以用于初始化定时器并赋值其成员,其源代码如下:
- static inline void setup_timer(struct timer_list * timer,
- void (*function)(unsigned long),
- unsigned long data)
- timer->function = function;
- timer->data = data;
- init_timer(timer);
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(struct timer_list *timer)等价板,主要用以多处理器中
5)修改定时器
- int del_timer(struct timer_list *timer);
- del_timer_sync(struct timer_list *timer);//为del_timer(struct timer_list *timer)等价板,主要用以多处理器中
- /*内核定时器使用模板*/
- struct xxx_dev//设备结构体
- {
- struct cdev cdev;
- ...
- timer_list xxx_timer;//设备要使用的定时器
- };
- //驱动中的某函数
- xxx_funci(...)
- {
- struct xxx_dev *dev=filp->private_data;
- ...
- //初始化定时器
- init_timer(&dev_>xxx_timer);
- dev->xxx_timer.function = &xxx_do_timer;
- dev->xxx_timer.data = (unsigned long)dev;//设备结构体指针作为处理函数参数
- dev->xxx_time.expires=jiffies+delay;
- /*添加(注册)定时器*/
- add_timer(&dev->xxx_timer);
- ...
- }
- //xxx驱动中的莫函数
- xxx_func2(...)
- {
- ...
- //删除定时器
- del_timer(&dev_>xxx_timer);
- ...
- }
- //定时器处理函数
- static void xxx_do_timer(unsigned long arg)
- {
- struct xxx_device *dev = (struct xxx_device *)(arg);
- ...
- //调度定时器再执行
- dev->xxx_timer.expires = jiffies +delay;
- add_timer(&dev->xxx_timer);
- ...
- }