內核在硬件的幫助下計算和管理時間。硬件爲內核提供一個系統定時器用以計算流逝的時間。系緩存
統定時器以某種頻率自行觸發,產生時鐘中斷,進入內核時鐘中斷處理程序中進行處理。數據結構
牆上時間和系統運行時間根據時鐘間隔來計算。函數
利用時間中斷週期執行的工做:spa
更新系統運行時間;code
更新實際時間;blog
在smp系統上,均衡調度程序中各處理器上運行隊列;隊列
檢查當前進程是否用盡了時間片,從新進行調度;進程
運行超時的動態定時器;事件
更新資源消耗和處理器時間的統計值;資源
系統定時器的頻率;經過靜態預處理定義的——HZ;系統啓動按照HZ值對硬件進行設置。體系結構不一樣,HZ值也不一樣;HZ可變的。
//內核時間頻率
#define HZ 1000
提升節拍率中斷產生更加頻繁帶來的好處:
提升時間驅動事件的解析度;
提升時間驅動事件的準確度;
內核定時器以更高的頻度和準確度;
依賴頂上執行的系統調用poll()和select()能更高的精度運行;
系統時間測量更精細;
提升進程搶佔的準確度;
提升節拍率帶來的反作用:
中斷頻率增高系統負擔增長;
中斷處理程序佔用處理器時間增多;
頻繁打斷處理器高速緩存;
節拍率HZ值須要在其中進行平衡。
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);
}