linux内核(2.6.28)操作定时器的数据结构为timer_list,timer_list结构体的一个实例对应一个定时器。
struct timer_list {
struct list_head entry;
unsigned long expires;
void (*function)(unsigned long);
unsigned long data;
struct tvec_base *base;
#ifdef CONFIG_TIMER_STATS
void *start_site;
char start_comm[16];
int start_pid;
#endif
};
1 定义一个定时器:
struct timer_list my_timer;
初始化定时器:
void init_timer(struct timer_list *timer);
TIMER_INITIALIZER由于复制timer_list结构体
#define TIMER_INITIALIZER(_function, _expires, _data) { /
.entry = { .prev = TIMER_ENTRY_STATIC }, /
.function = (_function), /
.expires = (_expires), /
.data = (_data), /
.base = &boot_tvec_bases, /
}
DEFINE_TIMER(_name, _function, _expires, _data)宏是定义并初始化定时器成员的快捷方式
#define DEFINE_TIMER(_name, _function, _expires, _data) /
struct timer_list _name = TIMER_INITIALIZER(_function, _expires, _data)
static inline void setup_timer(struct timer_list * timer,void (*function)(unsigned long),unsigned long data)也可以与初始化定时器并复制其成员。
2 增加一个定时器
static inline void add_timer(struct timer_list *timer)用于注册内核定时器,将定时器加入到内核动态定时器链表
int del_timer(struct timer_list *timer)用于删除定时器
其中 del_timer_sync 是用在 SMP 系统上的(在非SMP系统上,它等于del_timer),当要被注销的定时器函数正在另一个 cpu 上运行时,del_timer_sync() 会等待其运行完,所以这个函数会休眠。另外还应避免它和被调度的函数争用同一个锁。对于一个已经被运行过且没有重新注册自己的定时器而言,注销函数其实也没什么事可做。
3 重新注册
要修改一个定时器的调度时间,可以通过调用 mod_timer(struct timer_list *timer, unsigned long expires)。mod_timer() 会重新注册定时器到内核,而不管定时器函数是否被运行过。
4 int timer_pending(const struct timer_list *timer)
这个函数用来判断一个定时器是否被添加到了内核链表中以等待被调度运行。注意,当一个定时器函数即将要被运行前,内核会把相应的定时器从内核链表中删除(相当于注销)
5 在使用 struct timer_list 之前,需要初始化该数据结构,确保所有的字段都被正确地设置。初始化有3种方法。
方法一:
DEFINE_TIMER(timer_name, function_name, expires_value, data);
该宏会静态创建一个名叫 timer_name 内核定时器,并初始化其 function, expires, name 和 base 字段。
方法二:
struct timer_list mytimer;
setup_timer(&mytimer, (*function)(unsigned long), unsigned long data);
mytimer.expires = jiffies + 5*HZ;
方法3:
struct timer_list mytimer;
init_timer(&mytimer);
mytimer ->timer.expires = jiffies + 5*HZ;
mytimer ->timer.data = (unsigned long) dev;
mytimer ->timer.function = &corkscrew_timer; /* timer handler */