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;

}0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值