Linux內核學習筆記八——定時器和時間管理


一 內核中的時間觀念

       內核在硬件的幫助下計算和管理時間。硬件為內核提供一個系統定時器用以計算流逝的時間。系

 統定時器以某種頻率自行觸發,產生時鍾中斷,進入內核時鍾中斷處理程序中進行處理。

       牆上時間和系統運行時間根據時鍾間隔來計算。

利用時間中斷周期執行的工作:

       更新系統運行時間;

       更新實際時間;

       在smp系統上,均衡調度程序中各處理器上運行隊列;

       檢查當前進程是否用盡了時間片,重新進行調度;

       運行超時的動態定時器;

       更新資源消耗和處理器時間的統計值;

二 節拍率

       系統定時器的頻率;通過靜態預處理定義的——HZ;系統啟動按照HZ值對硬件進行設置。體系結構不同,HZ值也不同;HZ可變的。

    //內核時間頻率

    #define HZ 1000

提高節拍率中斷產生更加頻繁帶來的好處:

       提高時間驅動事件的解析度;

       提高時間驅動事件的准確度;

       內核定時器以更高的頻度和准確度;

       依賴頂上執行的系統調用poll()和select()能更高的精度運行;

       系統時間測量更精細;

       提高進程搶占的准確度;

提高節拍率帶來的副作用:

       中斷頻率增高系統負擔增加;

       中斷處理程序占用處理器時間增多;

       頻繁打斷處理器高速緩存;

節拍率HZ值需要在其中進行平衡。

 

三 jiffies

  jiffies:全局變量,用來記錄自系統啟動以來產生的節拍總數。啟動時內核將該變量初始化為0;

此后每次時鍾中斷處理程序增加該變量的值。每一秒鍾中斷次數HZ,jiffies一秒內增加HZ。系統運行時間 = jiffie/HZ.

jiffies用途:計算流逝時間和時間管理

jiffies內部表示:

              extern u64 jiffies_64;

              extern unsigned long volatile jiffies;     //位長更系統有關32/64

  32位:497天后溢出

  64位:……

      

//0.5秒后超時
 unsigned long timeout = jiffies + HZ/2; …… //注意jiffies值溢出回繞用宏time_before 而非 直timeout > jiffies
if(time_before(jiffies,timeout)){ //沒有超時
}else{ //超時
}

 

四 硬時鍾和定時器

  兩種設備進行計時:系統定時器和實時時鍾。

實時時鍾(RTC):用來持久存放系統時間的設備,即便系統關閉后,靠主板上的微型電池提供電力保持系統的計時。

    系統啟動內核通過讀取RTC來初始化牆上時間,改時間存放在xtime變量中。

系統定時器:內核定時機制,注冊中斷處理程序,周期性觸發中斷,響應中斷處理程序,進行處理執行以下工作:

  l  獲得xtime_lock鎖,訪問jiffies和更新牆上時間xtime;

  l  更新實時時鍾;

  l  更新資源統計值:當前進程耗時,系統時間等;

  l  執行已到期的動態定時器;

  l  執行scheduler_tick()

 

//中斷處理程序  irqreturn_t timer_interrupt(int irq, void *dev) { //ticks have passed
    long nticks; xtime_update(nticks); while (nticks--) update_process_times(user_mode(get_irq_regs())); return IRQ_HANDLED; } void xtime_update(unsigned long ticks) { //seq鎖
    write_seqlock(&xtime_lock); do_timer(ticks); write_sequnlock(&xtime_lock); } void do_timer(unsigned long ticks) { jiffies_64 += ticks; //更新牆上時間 ——實際時間
 update_wall_time(); calc_global_load(ticks); } void update_process_times(int user_tick) { struct task_struct *p = current; //計算當前進程執行時間
 account_process_tick(p, user_tick); //觸發軟中斷TIMER_SOFTIRQ 超時的timer
 run_local_timers(); //計算進程時間片
 scheduler_tick(); }

 

五 定時器

       定時器:管理內核時間的基礎,推后或執行時間執行某些代碼。

定時器數據結構:

struct timer_list { struct list_head entry; //定時值基於jiffies
              unsigned long expires; //定時器內部值
              struct tvec_base *base; //定時器處理函數
              void (*function)(unsigned long); //定時器處理函數參數
              unsigned long data; …… };

 

定時器使用:

    struct timer_list my_timer; //初始化定時器
       init_timer(&my_timer); …… //激活定時器
       add_timer(&my_timer); //刪除定時器
 del_timer(my_timer); ……

 

六 延遲執行

       使用定時器和下半部機制推遲執行任務。還有其他延遲執行的機制:

忙等待:

       利用節拍,精確率不高

       unsigned long delay = jiffies + 2*HZ ; //2秒 節拍整數倍才行;

       while(time_before(jiffies,delay))

              ;

短延遲:延遲時間精確到毫秒,微妙;短暫等待某個動作完成時,比時鍾節拍更短;依靠數次循環達到延遲效果。

       void udelay(unsigned long usecs)

       void mdelay(unsigned long msecs)

 

schedule_timeout()延遲:使執行的任務睡眠指定時間,達到延遲

 

signed long __sched schedule_timeout(signed long timeout) { struct timer_list timer; unsigned long expire; switch (timeout) {    case MAX_SCHEDULE_TIMEOUT: //無限期睡眠
 schedule(); goto out;   default: if (timeout < 0) { current->state = TASK_RUNNING; goto out; } } //超時時間
       expire = timeout + jiffies; //初始化一個timer定時器 參數current task
       setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); __mod_timer(&timer, expire, false, TIMER_NOT_PINNED); schedule(); del_singleshot_timer_sync(&timer); /* Remove the timer from the object tracker */ destroy_timer_on_stack(&timer); timeout = expire - jiffies; out: return timeout < 0 ? 0 : timeout; } static void process_timeout(unsigned long __data) { //喚醒被睡眠的任務 wake_up_process((struct task_struct *)__data); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM