1、定時器
之前說過兩類跟時間相關的核心結構。
1、延時:通過忙等待或者睡眠機制實現延時。
2、tasklet和工作隊列,通過某種機制使工作推後執行,但不知道執行的具體時間。
接下來要介紹的定時器,能夠使工作在指定的時間點上執行,而且不需要使用忙等待這類的延時方法。通過定義一個定時器,告之核心在哪個時間需要執行什麼函數就可以了,等時間一到,核心會就執行指定的函數。
2、使用定時器
定時器的使用很簡單,只需要三部:
1、定義定時器結構體timer_list。
2、設定逾時時間,定義定時器處理函數和傳參。
3、啟用定時器
代碼
#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/timer.h>#if 0 //定義並初始化定時器結構體timer_list。/*include/linux/timer.h*/struct timer_list {struct list_head entry;unsigned long expires; //設定在執行定時器處理函數的時間void (*function)(unsigned long); //定時器處理函數unsigned long data; //處理函數的傳參struct tvec_base *base;#ifdef CONFIG_TIMER_STATSvoid *start_site;char start_comm[16];int start_pid;#endif};#endifstruct timer_list my_timer; //1.定義定時器結構體timer_listvoid timer_func(unsigned long data) //2.定義定時器處理函數{printk("time out![%d] [%s]\n", (int)data, current->comm); //列印當前進程}static int __init test_init(void) //模組初始化函數{ init_timer(&my_timer); //1.初始化timer_list結構 my_timer.expires = jiffies + 5*HZ; //2.設定定時器處理函數觸發時間為5秒 my_timer.function = timer_func; //2.給結構體指定定時器處理函數 my_timer.data = (unsigned long)99; //2.設定定時器處理函數的傳參 add_timer(&my_timer); //3.啟用定時器 printk("hello timer,current->comm[%s]\n", current->comm); return 0; }static void __exit test_exit(void) //模組卸載函數{printk("good bye timer\n");}
三、定時器的刪除和修改
上面說了,啟用定時器後只能執行一遍,如果要實現隔指定時間又重複執行,那就要修改一下代碼。
在定時器處理函數中加上兩條代碼:
my_timer.expires = jiffies + 2*HZ; //重新設定時間,在兩秒後再執行
add_timer(&my_timer); //再次啟用定時器
這樣的話,每個2秒就會再次執行定時器處理函數。
這兩條代碼也相當與一下的函數:
mod_timer(&my_timer, jiffies + 2*HZ);
/*kernel/timer.c*/
int mod_timer(struct timer_list *timer, unsigned long expires)
這是改變定時器逾時時間的函數,如果在指定的定時器(timer)沒逾時前調用,逾時時間會更新為新的新的逾時時間(expires)。如果在定時器逾時後調用,那就相當於重新指定逾時時間並再次啟用定時器。
如果想在定時器沒有逾時前取消定時器,可以調用以下函數:
/*kernel/timer.c*/
int del_timer(struct timer_list *timer)
該函數用來刪除還沒逾時的定時器。