開發平臺 芯靈思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)
unsigned long msecs_to_jiffies(const unsigned int m)
Linux 內核定時器操作相關 API
靜態定義結構體變量并且初始化(宏)DEFINE_TIMER(_name, _function, _expires, _data)
功能: 定義一個名字為_name 的 struct timer_list 結構的變量, 并且初始化它的 function, expires, data 成員
init_timer(timer)
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/interrupt.h>
void tasklet_fun(unsigned long data);
//Step1 定義并靜態初始化tasklet_struct 結構變量
DECLARE_TASKLET(mytasklet, tasklet_fun, 651);
//Step2 tasklet服務函數
void tasklet_fun(unsigned long data)
{
static unsigned long count = 0;
printk("count:%lu,%s is call! data:%lu\r\n",count++,__FUNCTION__,data);
tasklet_schedule(&mytasklet); //在工作函數中重新調度自己,這樣會循環調用tasklet_fun
}
static int __init mytasklet_init(void)
{
//Step3 開始調度 mytasklet
tasklet_schedule(&mytasklet);
printk("%s is call!\r\n",__FUNCTION__);
return 0;
}
static void __exit mytasklet_exit(void) //Module exit function specified by module_exit()
{
//Step4 刪除 tasklet
tasklet_kill(&mytasklet);
}
module_init(mytasklet_init);
module_exit(mytasklet_exit);
MODULE_LICENSE("GPL");
實驗現象
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。