linux時間子系統(七)

簡單介紹linux下的時間子系統。包括clocksource,timekeeper和定時器的內容。node

3.2 高精度定時器 

  隨着內核的不斷升級和硬件的不斷髮展,因爲低精度定時器有必定的侷限性,內核從2.6.16開始加入了高精度定時器架構。在實現方式上,高精度定時器的實現代碼幾乎沒有借用低精度定時器的數據結構和代碼,緣由有如下幾點:linux

  1 低精度定時器的代碼和jiffies的關係太過緊密,而且默認按照32爲進行設計,若是要基於它來實現高精度時鐘,必然會打破原有的time wheel的概念,並且會引入大量的#if #else判斷。數組

  2 雖然大部分時間裏,time wheel能夠實現O(1)的時間複雜度,可是若是有進位發生,不可預測的O(n)定時器級聯遷移,大大的影響了高精度定時器的精度。數據結構

  3 低精度定時器幾乎爲超時而設計,爲此對它進行了大量的優化,精確時間並非它的主要目的。架構

  爲此,內核爲高精度定時器從新設計了一套軟件架構,他能夠爲咱們提供納秒級的定時精度,以知足對精確時間有迫切需求的應用和內核驅動,如多媒體應用,音頻設備的驅動程序等等。函數

3.2.1 hrtimer重要的數據結構

  低精度定時器使用5個鏈表數組來組織timer_list結構,造成了著名的時間輪的概念。而高精度時鐘,爲了具有穩定而快速的查找、快速的插入和刪除定時器的能力以及排序功能,內核的開發者最後選定紅黑樹,來組織hrtimer。隨着系統的運行,hrtimer不斷的被建立和銷燬,新的hrtimer按照到期時間被插入到紅黑樹中,紅黑樹的最左下節點即爲最快到期的定時器。內核使用hrtimer結構表示一個高精度定時器。優化

struct hrtimer {spa

        struct timerqueue_node          node;設計

        ktime_t                         _softexpires;rest

        enum hrtimer_restart            (*function)(struct hrtimer *);

        struct hrtimer_clock_base       *base;

        unsigned long                   state;

        struct list_head                cb_entry;

        int                             irqsafe;

#ifdef CONFIG_TIMER_STATS

        int                             start_pid;

        void                            *start_site;

        char                            start_comm[16];

#endif                  

};

   _softexpires,表示到期時間。

  function,定時器到期時的回調函數。其返回值是一個枚舉值,決定了該定時器是否須要被從新激活。若是返回值爲HRTIMER_RESTART,代表須要從新激活。若是爲HRTIMER_NORESTART,代表不須要從新激活。

  state,用於表示hrtimer當前的狀態。

#define HRTIMER_STATE_INACTIVE  0x00    //定時器未激活

#define HRTIMER_STATE_ENQUEUED  0x01    // 定時器已經排入紅黑樹中

#define HRTIMER_STATE_CALLBACK  0x02    // 定時器的回調函數正在被調用

#define HRTIMER_STATE_MIGRATE   0x04    // 定時器正在cpu間作遷移

   base,表示當前定時器是基於哪種時間基準的。hrtimer到期時間能夠基於如下幾種時間基準

enum  hrtimer_base_type {

        HRTIMER_BASE_MONOTONIC,    //monotonic time

        HRTIMER_BASE_REALTIME,    //wall time

        HRTIMER_BASE_BOOTTIME,    //boot time

        HRTIMER_MAX_CLOCK_BASES,

};

3.2.2 紅黑樹 

  與低精度時鐘同樣,處於效率和互斥的考慮,每一個cpu單獨管理屬於本身的hrtimer。爲此,專門定義了一個結構hrtimer_cpu_base:

struct hrtimer_cpu_base {

        raw_spinlock_t                  lock;

        unsigned long                   active_bases;

#ifdef CONFIG_HIGH_RES_TIMERS

        ktime_t                         expires_next;  //三種時間基準的定時器最早到期定時器的時間

        int                             hres_active;

        int                             hang_detected;

        unsigned long                   nr_events;

        unsigned long                   nr_retries;

        unsigned long                   nr_hangs;

        ktime_t                         max_hang_time;

#endif

#ifdef CONFIG_PREEMPT_RT_BASE

        wait_queue_head_t               wait;

#endif

        struct hrtimer_clock_base       clock_base[HRTIMER_MAX_CLOCK_BASES];  //每一個cpu都有三種時間基準的高精度定時器列表

};

 

struct hrtimer_clock_base {             

      struct hrtimer_cpu_base *cpu_base;  //指向所屬cpu的hrtimer_cpu_base結構

        int                     index;  

        clockid_t               clockid;  //肯定基於哪一種時間基準

        struct timerqueue_head  active;   //紅黑樹,含定時器列表

        struct list_head        expired;  

        ktime_t                 resolution;

        ktime_t                 (*get_time)(void);

        ktime_t                 softirq_time;

        ktime_t                 offset;

};

struct timerqueue_node {

        struct rb_node node;

        ktime_t expires;

};

 

struct timerqueue_head {

        struct rb_root head;

        struct timerqueue_node *next;

};

   timequeue_head結構在紅黑樹的基礎上,增長了一個next字段,用於保存紅黑樹中最早到期的定時器節點,實際上就是紅黑樹的最左下節點。有了next字段,系統就沒必要遍歷整個紅黑樹,只要取出next字段對應的節點處理便可。

相關文章
相關標籤/搜索