Linux內核2.4版中去掉了老版本內核中的靜態定時器機制,而只留下動態定時器。相應地在timer_bh()函數中也不再通 過run_old_timers()函數來運行老式的靜態定時器。動態定時器與靜態定時器這二個概念是相對於Linux內核定時器機制的可擴展功能而言的,動態定時器是指內核的定時器隊列是可以動態變化的,然而就定時器本身而言,二者並無本質的區別。考慮到靜態定時器機制的能力有限,因此Linux內核2.4版中完全去掉了以前的靜態定時器機制。
7.6.1 Linux內核對定時器的描述
Linux在include/linux/timer.h頭文件中定義了數據結構timer_list來描述一個內核定時器:
struct timer_list {
struct list_head list;
unsigned long expires;
unsigned long data;
void (*function)(unsigned long);
};
各數據成員的含義如下:
(1)雙向鏈表元素list:用來將多個定時器連接成一條雙向循環隊列。
(2)expires:指定定時器到期的時間,這個時間被表示成自系統啟動以來的時鐘滴答計數(也即時鐘節拍數)。當一個
定時器的expires值小於或等於jiffies變量時,我們就說這個定時器已經超時或到期了。在初始化一個定時器後,通常
把它的expires域設置成當前expires變量的當前值加上某個時間間隔值(以時鐘滴答次數計)。
(3)函數指針function:指向一個可執行函數。當定時器到期時,內核就執行function所指定的函數。而data域則
被內核用作function函數的調用參數。
內核函數init_timer()用來初始化一個定時器。實際上,這個初始化函數僅僅將結構中的list成員初始化為空。如下所示(include/linux/timer.h):
static inline void init_timer(struct timer_list * timer)
{
timer->list.next = timer->list.prev = NULL;
}
由於定時器通常被連接在一個雙向循環隊列中等待執行(此時我們說定時器處於pending狀態)。因此函數time_pending()
就可以用list成員是否為空來判斷一個定時器是否處於pending狀態。如下所示
(include/linux/timer.h):
static inline int timer_pending (const struct timer_list * timer)
{
return timer->list.next != NULL;
}
時間比較操作
在定時器應用中經常需要比較兩個時間值,以確定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)