linux之延時及核心定時器的使用
想要在核心中的實行短的延時我們可以看這兩個標頭檔案Linux-3.0.1\include\linux下的delay.h和linux-3.0.1\arch\arm\include\asm下的delay.h裡面包含了這樣幾句延時的語句
void ndelay(unsigned long nsecs); //納秒級的延時
void udelay(unsigned long usecs); //微妙級的延時
void mdelay(unsigned long msecs); //毫秒級的延時
用這三個函式我們要重點知道他們是忙等待函式,因此在延時的同時其它程式是無法執行的,如果涉及到毫秒級以上的延時我個人不推薦使用mdelay
void msleep(unsigned int millsecs); //毫秒級睡眠
unsigned long msleep_interruptible(unsigned int millsecs); //毫秒級帶有中斷喚醒的延時(通常返回值為0,但是如果提前被喚醒則返回剩餘毫秒數)
void ssleep(unsigned int seconds) //秒級的延時
個人認為這些延時過程當中系統在進行任務的排程,當延時時間到達時,核心在直接排程這個程序。
核心定時器是基於滴答時鐘實現定時,如果我們需要在將來的某一個時刻讓核心排程執行某段程式,同時在這個時刻到來之前不會阻塞當前程序。
核心定時器的使用只有3個步驟
1.定義定時器結構體
struct timer_list {
struct list_head entry; //定時器列表
unsigned long expires; //定時器到期時間
struct tvec_base *base;
void (*function)(unsigned long); //定時器中斷處理函式
unsigned long data; //作為引數可以傳入定時器中斷處理函式
};
2.給定時器結構體賦定時時間、定時中斷處理函式、傳參設定。
在這裡我講一下定時的數值該怎麼來確定,因為核心定時器是基於jiffies,所以設定的時間要在jiffies
3.啟用定時器add_timer;
對於上面的第2步,涉及到靜態定義和動態定義兩種方法
靜態定義struct timer_list TIMER_INITIALIZER(_function, _expires, _data);
直接把中斷函式,到期時間,傳入引數寫上即可。
動態定義,就是我們一般的對結構體賦值,非常簡單。不過在賦值之前我們先必須初始化timer_list這個結構體,如init_timer(&結構體名);
完成以上步驟之後我們就可以呼叫add_timer函式來啟用定時器開始定時。
當我們啟用定時器後,它只會執行一次處理函式,然後將定時器從核心中移除。但我們平時往往需要重複執行,所以核心給我嗎提供了int mod_timer(struct timer_list *timer, unsigned long expires)。
在不用定時器的時候我們需要int del_timer(struct timer_list *timer)需要刪除定時器。
最後講一下核心是如何來管理定時器的,當我們啟動一個定時器的時候,定時器並不是右我們當前載入的模組來管理,而是由核心的swapper程序來接管了這個定時器,當定時器時間一到。核心將呼叫swapper程序執行函式。