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 */