芯靈思Sinlinx A64開發板Linux內核定時器編程
阿新 • • 發佈:2019-03-12
ati function long entry fan str 進行 mask 相關 開發平臺 芯靈思Sinlinx A64
內存: 1GB 存儲: 4GB
開發板詳細參數 https://m.tb.cn/h.3wMaSKm
開發板交流群 641395230
Linux 內核定時器是內核用來控制在未來某個時間點(基於jiffies)調度執行某個函數的一種機制,其實現位於 <Linux/timer.h> 和 kernel/timer.c 文件中。
內核定時器的數據結構
struct timer_list { struct list_head entry; //雙向鏈表元素list:用來將多個定時器連接成一條雙向循環隊列。 unsigned long expires; //expires 字段表示期望定時器執行的 jiffies 值,到達該 jiffies 值時,將調用 function 函數,並傳遞 data 作為參數。 void (*function)(unsigned long); //指向一個可執行函數。當定時器到期時,內核就執行function所指定的函數。而data域則被內核用作function函數的調用參數。 unsigned long data; struct tvec_base *base; /* ... */ };
時間比較操作
在定時器應用中經常需要比較兩個時間值,以確定timer是否超時,所以Linux內核在timer.h頭文件中定義了4個時間關系比較操作宏。這裏我們說時刻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 內核時間相關轉換函數
- unsigned long usecs_to_jiffies(const unsigned int u)
功能: 把微秒轉換成時鐘節拍
參數: u 時間微秒
返回: 對應的時鐘節拍數量 - unsigned long msecs_to_jiffies(const unsigned int m)
功能: 把毫秒轉換成時鐘節拍
參數: u 時間毫秒
返回: 對應的時鐘節拍數量
示例: 要定時從現在開始, 3 毫秒執行一個函數
expires 設置為 jiffies+ msecs_to_jiffies(3)
Linux 內核定時器操作相關 API
-
靜態定義結構體變量並且初始化(宏)
功能: 定義一個名字為_name 的 struct timer_list 結構的變量, 並且初始化它的 function, expires, data 成員 - 定時器初始化(宏)
init_timer(timer)
功能: 只是對 struct timer_list 結構成員進行一些基礎初始化操作, function, expires, data 成員還需要用戶自
己填充。
3.設置定時器(宏)
setup_timer(timer, fn, data)
功能: 設置定時器中的 function, data 和一些基礎成員, expires 並沒有初始化, 需要用戶自己進行初始化
-
註冊定時器到內核
void add_timer(struct timer_list timer)
功能: 向內核註冊一個定時器, 註冊後會馬上開始計時。
5.從內核註銷定時器
int del_timer(struct timer_list timer);
功能: 從內核定時鏈表上刪除指定的定時器, 刪除後就不會再執行綁定的函數 - 修改定時器定時時間值, 並且重新註冊
int mod_timer(struct timer_list *timer, unsigned long expire0.s);
功能: 修改定時器定時時間值, 並且重新註冊, 不管這個定時的超時函數是否執行過。 執行完成後會馬上啟
動定時。
內核定時器編程步驟
Step1 定義timer_list 結構變量
Step2 定義超時函數
Step3 對timer_list結構變量進行初始化
Step4 註冊定時器,啟動定時
Step5 註銷定時器
驅動代碼:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
//Step1 timer_list 結構變量
struct timer_list timer;
//Step2 超時函數
void timer_fun(long data)
{
printk("%s is call! data:%d\r\n",__FUNCTION__,data);//__FUNCTION__ 獲取當前函數名
mod_timer(&timer, jiffies + HZ*1); //再次修改本定時器超時時間為當前時間後1秒
}
static int __init timer_init(void)
{
//Step3 對timer_list結構變量進行初始
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.4
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += timer_drv.o
最後使用 dmseg 命令查看,可以看到每隔1秒打印一次
芯靈思Sinlinx A64開發板Linux內核定時器編程