Linux系統定時器,在內核中扮演著重要角色。內核的許多重要實現如任務調度,工作隊列等均以系統定時器關系密切。系統定時器能以可編程的頻率中斷處理,這一中斷叫做軟中斷。此頻率即為每秒的定時器節拍數HZ。HZ的越大,說明定時器節拍越小,線程調度的准確性會越高。但HZ設得過大,對一個系統來說並不好,會導CPU開銷過大,反而造成任務調度效率降低。滴答jiffies 變量記錄系統啟動以來,系統定時器已經觸發的次數。也就是說每過一秒jiffies的增量為HZ,一般HZ=100,HZ是可以配置的,在S3C2440 arm linux中配置為200.
下面基於Linux2.6.30.4源碼來探討其實現原理及其過程。
要理解系統定時器實現原理,先來看看關系到系統定時器的各種數據結構,其具體的描述參數。
結構體structtimer_list來描述timer的參數,其數據結構如下:
[cpp]
- struct timer_list {
- structlist_head entry; //timer雙向鏈表
- unsignedlong expires; //timer超時變量
-
- void(*function)(unsigned long); //timer超時回調函數 www.linuxidc.com
- unsignedlong data; //傳遞給回調函數的數據,也就是定時器數據
- struct tvec_base *base; //timer base向量表用於timer_list的掛載和鏈表管理
- //timer的一些擴展參數
- #ifdef CONFIG_TIMER_STATS
- void*start_site;
- charstart_comm[16];
- intstart_pid;
- #endif
- #ifdef CONFIG_LOCKDEP
- structlockdep_map lockdep_map;
- #endif
- };
其中:
[cpp]
- list_entry結構:
- struct list_head {
- structlist_head *next, *prev;
- };
- tevc_base的結構:
- struct tvec_base {
- spinlock_tlock; //自旋鎖lock
- structtimer_list *running_timer; //指向已經掛載進來的timer_list
- unsignedlong timer_jiffies; //timer jiffies用於記錄定時器當前jiffies
- structtvec_root tv1; //5組tvec_base,從tv1~tv5,成員數各不相同
- structtvec tv2; //其成員數TVR_SIZE,TVN_SIZE決定
- structtvec tv3;
- structtvec tv4;
- structtvec tv5;
- } ____cacheline_aligned;
-
- #define TVN_BITS (CONFIG_BASE_SMALL ? 4 :6)
- #define TVR_BITS (CONFIG_BASE_SMALL ? 6 :8)
- #define TVN_SIZE (1 << TVN_BITS)
- #define TVR_SIZE (1 << TVR_BITS)
- #define TVN_MASK (TVN_SIZE - 1)
- #define TVR_MASK (TVR_SIZE - 1)
-
- struct tvec {
- structlist_head vec[TVN_SIZE]; // tv2~t5個數為64的數組
- };
-
- struct tvec_root {
- structlist_head vec[TVR_SIZE]; //tv1個數為256的數組
- };