linux定时器回调处理过程,Linux内核系统定时器TIMER实现过程分析
可見涉及到系統定時器的數據結構并不多,那么:對于一個linux系統中,定時器個數可能會很多,而且每個定時器的超時事件時間并不相同,所以如何管理和處理定時器超時事件,關系到內核性能的高低。它根據不同的定時事件,按時間間分組,將新增的timer定時器建成雙向鏈表,然后按照一定方式存放于5組tv1~tv5變量中稱為tec_base。對于對稱式多理器(SMP)系統還考慮到了TIMER從一個CPU遷移到另一個CPU的情況,相應的tev_base也跟著更改。那它在系統是怎樣實現的呢?現在先從一個簡單的系統定時器應用例子來看看它的實現過程:
[cpp]
#include?
#include?
#include?
structtimer_list???my_timer;
staticvoidmy_function(unsignedlongdata)
{
staticinti?=?0;
printk("timer’s?callback?function\n");
printk("timer’s?data?=?%lu\n",data);
return;
}
staticintmy_timer_init(void)
{
printk(“timerinit…\n”);
my_timer.data?=?0xff;
my_timer.function?=?my_function;
my_timer.expires?=?jiffies?+?3*HZ;
init_timer(&my_timer);
add_timer(&my_timer);
return0;
}
staticvoidmy_timer_exit(void)
{
printk("timer?exit…\n");
}
module_init(my_timer_init);
module_exit(my_timer_exit);
MODULE_AUTHOR("itspy");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("linux?kernel?timerprogramming");
上面例子,實現了一個定時器事件,將在3 HZ(秒)發生。my_imer_init函數中調用到的定時器API只有:
init_timer(&my_timer);?? //用于定時器初始化
add_timer(&my_timer);??? //增加一個新的定時器到tev_base向量表中
其中init_timer中調用了__init_timer(),這個函數才是真正初始化定時器的:
[cpp]
staticvoid__init_timer(structtimer_list*timer,
constchar*name,
structlock_class_key?*key)
{
timer->entry.next=?NULL;//對于新增的timer實例,其下一各總是指向NULL。
timer->base=?__raw_get_cpu_var(tvec_bases);//SMP中,獲得當前處理器的tev_base
//這個tev_bases是根據一定規律變化的,稍后會將到
…
}
新增的定時器初始化,就是完成了一個timer_list結構初始化過程。
add_timer() ?--> mod_timer() ?--> ?__mod_timer()其中:
[cpp]
staticinlineint
__mod_timer(structtimer_list?*timer,unsignedlongexpires,boolpending_only)
{
structtvec_base?*base,?*new_base;
unsignedlong?flags;
intret;
ret=?0;
BUG_ON(!timer->function);//?BUG檢測,確保回調函數為非空NULL
base=?lock_timer_base(timer,?&flags);//獲取本地cpu的tev_base,這是一個臨
//界資源,里邊是一個for(;;)循環,如果找不到說明已經遷移到了別的CPU
if(timer_pending(timer))?{//當已掛載的timer?定時超時發生后,會被卸載摘除
detach_timer(timer,0);
ret=?1;
}else{
if(pending_only)//新增一個定時器時,pending_only?為?false
gotoout_unlock;
}
…
new_base=?__get_cpu_var(tvec_bases);//獲取本地cpu中的tevc_bases
if(base?!=?new_base)?{//由于之前base?可能已被遷移到其他CPU的?tev_base向量表,會造成?base?!=?new_base
if(likely(base->running_timer?!=?timer))?{//由于在timer正在運行時,我們不能直接更改base,位與一個叫做DEFERRABLE(可延后標志)后處理
/*See?the?comment?in?lock_timer_base()?*/
timer_set_base(timer,NULL);
spin_unlock(&base->lock);
base=?new_base;
spin_lock(&base->lock);
timer_set_base(timer,base);
}
}
timer->expires=?expires;
internal_add_timer(base,timer);//分析timer?expires及建表過程
out_unlock:
spin_unlock_irqrestore(&base->lock,flags);
returnret;
}
總結
以上是生活随笔為你收集整理的linux定时器回调处理过程,Linux内核系统定时器TIMER实现过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谁玩王者V区
- 下一篇: linux 其他常用命令