核心用來控制在未來某個時間點(基於jiffies)排程執行某個函式的一種機制。
被排程的函式是非同步執行的,它類似於一種「軟體中斷」,而且是處於非程序的上下文中,所以排程函式必須遵守以下規則:
1) 沒有 current 指標、不允許訪問使用者空間。因為沒有程序上下文,相關**和被中斷的程序沒有任何聯絡。
2) 不能執行休眠(或可能引起休眠的函式)和排程。
3) 任何被訪問的資料結構都應該針對併發訪問進行保護,以防止競爭條件。
核心定時器的資料結構
struct timer_list ;
其中有3個公共字段需要我們關注,分別為expires,function,data。
expires 字段表示期望定時器執行的 jiffies 值,需要注意的是 expires 的值是32位的,因為核心定時器並不適用於長的未來時間點。
到達該 jiffies 值時,將呼叫 function 函式,並傳遞 data 作為引數(如果需要通過這個引數傳遞多個資料項,那麼可以將這些資料項**成乙個資料結構,然後將該資料結構的指標強制轉換為unsigned long傳入,這種技巧在所有核心支援的體系建構上都是安全的)。
需要注意的是:核心定時器的排程函式執行過一次後就不會再被執行了(相當於自動登出),但可以通過在被排程的函式中重新排程自己來週期執行。
啟用乙個全新的核心定時器需要如下2個步驟:
1:初始化並且正確設定3個公共字段(expires,function,data)
在使用 struct timer_list 之前,需要初始化該資料結構,確保所有的字段都被正確地設定。初始化有3種方法。
方法1(靜態建立):
define_timer(timer_name, function_name, expires_value, data);
該巨集會靜態建立乙個名叫 timer_name 核心定時器,並初始化其 function, expires, name 和 base 字段。
方法2(動態建立):
struct timer_list mytimer;
setup_timer(&mytimer, (*function)(unsigned long), unsigned long data);
mytimer.expires = jiffies + 5*hz;
方法3(動態建立):
struct timer_list mytimer;
init_timer(&mytimer);
mytimer ->timer.expires = jiffies + 5*hz;
mytimer ->timer.data = (unsigned long) dev;
mytimer ->timer.function = &corkscrew_timer; /* timer handler */
通過init_timer()動態地定義乙個定時器,此後,將處理函式的位址和引數繫結給乙個timer_list。
注意,無論用哪種方法初始化,其本質都只是給字段賦值,所以只要在執行 add_timer() 之前,expires, function 和 data 欄位都可以直接再修改。
2:註冊
定時器要生效,還必須被連線到核心專門的鍊錶中,這可以通過 add_timer(struct timer_list *timer) 來實現。
要修改乙個定時器的排程時間,可以通過呼叫 mod_timer(struct timer_list *timer, unsigned long expires)。mod_timer() 會重新註冊定時器到核心,而不管定時器函式是否被執行過。
當不使用某個核心定時器時,需要將其登出:
登出乙個定時器,可以通過 del_timer(struct timer_list *timer) 或 del_timer_sync(struct timer_list *timer)。其中 del_timer_sync 是用在 smp 系統上的(在非smp系統上,它等於del_timer),當要被登出的定時器函式正在另乙個 cpu 上執行時,del_timer_sync() 會等待其執行完,所以這個函式會休眠。另外還應避免它和被排程的函式爭用同乙個鎖。對於乙個已經被執行過且沒有重新註冊自己的定時器而言,登出函式其實也沒什麼事可做。
核心定時器
linux核心2.4版中去掉了老版本核心中的靜態定時器機制,而只留下動態定時器。相應地在timer bh 函式中也不再通過 run old timers 函式來執行老式的靜態定時器。動態定時器與靜態定時器這二個概念是相對於linux核心定時器機制的可擴充套件 功能而言的,動態定時器是指核心的定時器佇...
核心定時器
核心中最終的計時資源是定時器。定時器用於定時器超時處理程式在未來某個特定時間點執行,或者週期性的輪詢硬體的狀態。linux提供了核心定時器完成這類工作。定 時器的只需要執行一些初始化的操作,如 設定乙個超時時間,指定超時要呼叫的函式,然後啟用定時器就可以了。它的處理和工作佇列還是有點類似的。和任務隊...
核心定時器,
ldd3 當定時器執行時 排程該定時器的程序可能正在睡眠,或在其它處理器上執行,或乾脆推出。沒有執行定時器,排程它的程式推出了,定時器該如何?2.6.35。22核心 gcc 4.4.5 include include include include include include include i...