全志A33開發(fā)板Linux內(nèi)核定時器編程
Linux 內(nèi)核定時器是內(nèi)核用來控制在未來某個時間點(基于jiffies)調(diào)度執(zhí)行某個函數(shù)的一種機制,其實現(xiàn)位于 和 kernel/timer.c 文件中。
內(nèi)核定時器的數(shù)據(jù)結(jié)構(gòu)struct timer_list {? ? struct list_head entry;? //雙向鏈表元素list:用來將多個定時器連接成一條雙向循環(huán)隊列。? ? unsigned long expires; //expires 字段表示期望定時器執(zhí)行的 jiffies 值,到達該 jiffies 值時,將調(diào)用 function 函數(shù),并傳遞 data 作為參數(shù)。? ? void (*function)(unsigned long); //指向一個可執(zhí)行函數(shù)。當定時器到期時,內(nèi)核就執(zhí)行function所指定的函數(shù)。而data域則被內(nèi)核用作function函數(shù)的調(diào)用參數(shù)。? ? unsigned long data;? ? ?struct tvec_base *base;? ? /* ... */}時間比較操作在定時器應(yīng)用中經(jīng)常需要比較兩個時間值,以確定timer是否超時,所以Linux內(nèi)核在timer.h頭文件中定義了4個時間關(guān)系比較操作宏。這里我們說時刻a在時刻b之后,就意味著時間值a≥b。Linux強烈推薦用戶使用它所定義的下列4個時間比較操作宏(include/linux/timer.h):
#define time_after(a,b) ((long)(b) - (long)(a) < 0) #define time_before(a,b) time_after(b,a) #define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0) #define time_before_eq(a,b) time_after_eq(b,a)Linux 內(nèi)核時間相關(guān)轉(zhuǎn)換函數(shù)1. unsigned long usecs_to_jiffies(const unsigned int u)功能: 把微秒轉(zhuǎn)換成時鐘節(jié)拍
參數(shù): u 時間微秒
返回: 對應(yīng)的時鐘節(jié)拍數(shù)量
2. unsigned long msecs_to_jiffies(const unsigned int m)功能: 把毫秒轉(zhuǎn)換成時鐘節(jié)拍
參數(shù): u 時間毫秒
返回: 對應(yīng)的時鐘節(jié)拍數(shù)量
示例: 要定時從現(xiàn)在開始, 3 毫秒執(zhí)行一個函數(shù)
expires 設(shè)置為 jiffies+ msecs_to_jiffies(3)
Linux 內(nèi)核定時器操作相關(guān) API靜態(tài)定義結(jié)構(gòu)體變量并且初始化(宏)
DEFINE_TIMER(_name, _function, _expires, _data)
功能: 定義一個名字為_name 的 struct timer_list 結(jié)構(gòu)的變量, 并且初始化它的 function, expires, data 成員定時器初始化(宏)
init_timer(timer)
功能: 只是對 struct timer_list 結(jié)構(gòu)成員進行一些基礎(chǔ)初始化操作, function, expires, data 成員還需要用戶自
己填充。3.設(shè)置定時器(宏)
setup_timer(timer, fn, data)
功能: 設(shè)置定時器中的 function, data 和一些基礎(chǔ)成員, expires 并沒有初始化, 需要用戶自己進行初始化
注冊定時器到內(nèi)核
void add_timer(struct timer_list timer)
功能: 向內(nèi)核注冊一個定時器, 注冊后會馬上開始計時。
從內(nèi)核注銷定時器
int del_timer(struct timer_list timer);
功能: 從內(nèi)核定時鏈表上刪除指定的定時器, 刪除后就不會再執(zhí)行綁定的函數(shù)
修改定時器定時時間值, 并且重新注冊
int mod_timer(struct timer_list timer, unsigned long expire0.s);
功能: 修改定時器定時時間值, 并且重新注冊, 不管這個定時的超時函數(shù)是否執(zhí)行過。 執(zhí)行完成后會馬上啟
動定時。
內(nèi)核定時器編程步驟Step1 定義timer_list 結(jié)構(gòu)變量Step2 定義超時函數(shù)Step3 對timer_list結(jié)構(gòu)變量進行初始化Step4 注冊定時器,啟動定時Step5 注銷定時器實驗平臺:芯靈思SinlinxA33開發(fā)板驅(qū)動代碼:#include <linux/module.h>#include <linux/init.h>#include <linux/timer.h>//Step1 timer_list 結(jié)構(gòu)變量struct timer_list timer;//Step2 超時函數(shù)void timer_fun(long data){? ? ? ? printk("%s is call! data:%d\r\n",__FUNCTION__,data);//__FUNCTION__? ?獲取當前函數(shù)名? ? ? ? mod_timer(&timer, jiffies + HZ*1); //再次修改本定時器超時時間為當前時間后1秒}static int __init timer_init(void){? ? ? ? //Step3 對timer_list結(jié)構(gòu)變量進行初始? ? ? ? init_timer(&timer);? ? ? ? setup_timer(&timer, timer_fun, 666);? ? ? ? timer.expires = jiffies + HZ*2;? ? ? ? //Step4 注冊定時器,啟動定時? ? ? ? add_timer(&timer);? ? ? ? ?printk("Timer start!\r\n");? ? ? ? return 0;}static void __exit timer_exit(void) //Module exit function specified by module_exit(){? ? ? ? //Step5 注銷定時器? ? ? ? del_timer_sync(&timer);? ? ? ? printk("Timer over!\r\n");}module_init(timer_init);module_exit(timer_exit);MODULE_LICENSE("GPL");Makefile代碼:KERN_DIR = /work/lichee/linux-3.4all:? ? ? ? make -C $(KERN_DIR) M=`pwd` modules clean:? ? ? ? make -C $(KERN_DIR) M=`pwd` modules clean? ? ? ? rm -rf modules.orderobj-m? ? ? ? += timer_drv.o最后使用 dmseg 命令查看,可以看到每隔1秒打印一次
了解更多相關(guān)內(nèi)容歡迎關(guān)注http://www.vecloud.com/