本文為我學習時所寫,非百分之百原創,望指出錯誤之處。
參考資料:
linux驅動之定時器(mod_timer)
核心定時器的使用(好幾個例子add_timer)
linux核心高精度定時器hrtimer 使用例項
hrtimer的簡單使用 + 原理和實現
定時器被排程的函式肯定是非同步執行的,它類似於一種「軟體中斷」,而且是處於非程序的上下文中,所以定時器排程函式必須遵守以下規則:
沒有 current 指標、不允許訪問使用者空間。因為沒有程序上下文,相關**和被中斷的程序沒有任何聯絡。
不能執行休眠(或可能引起休眠的函式)和排程。
任何被訪問的資料結構都應該針對併發訪問進行保護,以防止競爭條件。
linux核心中定義了定時器結構,struct timer_list,該結構如下:
#include
struct timer_list
;
void
init_timer
(struct timer_list * timer)
;/*函式init_timer用來初始化定時器,還有另外幾種方法可以用來初始化定時器,如下:*/
define_timer
(timer_name, function_name, expires_value, data)
;/*巨集define_timer,該巨集會靜態建立乙個名叫 timer_name 核心定時器,並初始化其 function, expires, name 和 base 字段。*/
以上為為定時器初始化的方式,初始話之後還需要將定時器註冊到核心定時器才會工作,所以一直在將定時器註冊到核心之前都可以修改定時器struct timer_list的字段。以下函式為定時器註冊函式:
void
add_timer
(struct timer_list * timer)
;//該函式將初始化之後的定時器
執行add_timer函式之後,會將定時器timer加入到核心鍊錶中
如果我們在定時器註冊到核心之後需要修改定時器指定的時間,那麼可以使用以下函式:
int
mod_timer
(struct timer_list *timer,
unsigned
long expires)
;/*函式mod_timer,該函式將定時器timer的定時時間修改為expires,並且會將定時器註冊到核心中*/
以上函式可以實現修改已經註冊到核心中的定時器的定時時間,需要注意的是,該函式不管定時器timer是否執行過,也不管定時器是不是已經註冊到核心中去,修改時間之後都會重新註冊定時器到核心。
可以通過以下函式對註冊到核心的定時器進行登出:
intdel_timer
(struct timer_list *timer);
intdel_timer_sync
(struct timer_list *timer);
/*將定時器timer從核心等待佇列中登出*/
以上兩個函式如果是在非smp系統上呼叫時,是沒有差別的;但是如果是在smp系統(對稱多處理機)上時,就需要注意了。當想要摘除定時器timer時,呼叫del_timer函式摘除,該函式首先會判斷該物件是不是處在pending狀態,乙個處於pengding狀態的定時器是處在核心的定時器管理佇列中正等待被排程執行的定時器物件,那麼這種情況下del_timer函式能夠正確的將定時器從核心鍊錶中摘除,如果timer物件已經被排程執行(核心原始碼稱這種定時器狀態為inactive),函式將直接返回0。呼叫del_timer_sync函式執行摘除時,他會確保當函式返回時系統中沒有任何處理器正在執行定時器物件上的定時器函式,而如果只是呼叫del_timer,那麼當函式返回時,被刪除的定時器物件的定時器函式可能正在其他處理器上執行。
int
timer_pending
(const
struct timer_list *timer)
;/*該函式用來判斷定時器timer是否在pending狀態*/
值得注意的是,定時器在執行過一次之後,就會將自己從核心的定時器管理佇列中摘除掉,等效於使用del_timer函式摘除。
linux核心高精度定時器hrtimer
核心為高精度定時器重新設計了一套軟體架構,它可以為我們提供納秒級的定時精度,以滿足對精確時間有迫切需求的應用程式或核心驅動,以下學習使用hrtimer(high resolution timer)高精度定時器。
linux核心使用結構體struct hrtimer來描述乙個高精度定時器hrtimer,如下所示:
struct hrtimer
;/*聯合體num hrtimer_restart*/
enum hrtimer_restart
;
以下為使用定時器hrtimer的一些api。
void
hrtimer_init
(struct hrtimer *timer, clockid_t which_clock,
enum hrtimer_mode mode)
;/*函式hrtimer_init,初始化乙個定時器timer,引數which_clock,可以是clock_realtime、clock_monotonic、clock_boottime中的一種
;引數mode,可以是相對時間hrtimer_mode_rel,也可以是絕對時間hrtimer_mode_abs。*/
inthrtimer_start
(struct hrtimer *timer, ktime_t tim,
const
enum hrtimer_mode mode)
;/*函式hrtimer_start,用來啟用已經初始化過的hrtimer 定時器。引數tim是定時器裝置的超時時間,因為timer內部
是使用的絕對時間來表示的,所以當我們的tim表示的是相對時間的時候,就需要先將相對時間轉換為絕對時間,即當引數mode為hrtimer_mode_rel時,
就需要進行轉換,可以使用ktime_set來進行轉換;引數mode,表示tim使用的是相對時間還是絕對時間*/
inthrtimer_cancel
(struct hrtimer *timer)
;/*函式hrtimer_cancel,用來取消乙個hrtimer*/
定時器驅動
想要每次進tick的時間相同如,每秒進100次tick tick想要100次 秒,那乙個tick就是1ms,而系統時鐘頻率是12 000 000 12 000 000hz 100hz,就是時鐘頻率除以tick頻率,翻譯過來就是每秒的時鐘滴答次數 每秒的tick次數等於乙個tick多少次時鐘滴答,然後...
linux核心驅動之定時器
運用場景 1.初始化乙個驅動,經過一定的時間再執行乙個特殊動作 2.初始化乙個驅動,之後每隔一定的時間執行乙個特殊動作 定時器工作流程 a.建立timer,編寫定時器處理函式 b.為timer的expires data function賦值 c.呼叫add timer將timer加入列表 d.定時器...
LINUX驅動程式設計 核心定時器
timer list結構體 struct timer list 1,定義乙個timer list定時器 struct timer list my timer 2,初始化定時器 1 void init timer struct timer list timer 上述init timer 函式初始化ti...