注册时钟事件监听器

5.1.3 注册时钟事件监听器

由于我们在.config文件中设置了CONFIG_GENERIC_CLOCKEVENTS,所以,start_kernel函数的第558行调用kernel/time/tick-common.c中的tick_init函数,来注册一个时钟事件监听器。tick_init只调用一个clockevents_register_notifier函数:

 

static struct notifier_block tick_notifier = {

       .notifier_call = tick_notify,

};

 

void __init tick_init(void)

{

       clockevents_register_notifier(&tick_notifier);

}

 

int clockevents_register_notifier(struct notifier_block *nb)

{

       unsigned long flags;

       int ret;

 

       raw_spin_lock_irqsave(&clockevents_lock, flags);

       ret = raw_notifier_chain_register(&clockevents_chain, nb);

       raw_spin_unlock_irqrestore(&clockevents_lock, flags);

 

       return ret;

}

 

这个函数很简单,只要先明白一个notifier_block结构就行了:

struct notifier_block {

       int (*notifier_call)(struct notifier_block *, unsigned long, void *);

       struct notifier_block *next;

       int priority;

};

 

tick_notifier全局变量在编译vmlinux的时候其notifier_call被设置成了tick_notify函数:

 

static int tick_notify(struct notifier_block *nb, unsigned long reason,

                            void *dev)

{

       switch (reason) {

 

       case CLOCK_EVT_NOTIFY_ADD:

              return tick_check_new_device(dev);

 

       case CLOCK_EVT_NOTIFY_BROADCAST_ON:

       case CLOCK_EVT_NOTIFY_BROADCAST_OFF:

       case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:

              tick_broadcast_on_off(reason, dev);

              break;

 

       case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:

       case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:

              tick_broadcast_oneshot_control(reason);

              break;

 

       case CLOCK_EVT_NOTIFY_CPU_DYING:

              tick_handover_do_timer(dev);

              break;

 

       case CLOCK_EVT_NOTIFY_CPU_DEAD:

              tick_shutdown_broadcast_oneshot(dev);

              tick_shutdown_broadcast(dev);

              tick_shutdown(dev);

              break;

 

       case CLOCK_EVT_NOTIFY_SUSPEND:

              tick_suspend();

              tick_suspend_broadcast();

              break;

 

       case CLOCK_EVT_NOTIFY_RESUME:

              tick_resume();

              break;

 

       default:

              break;

       }

 

       return NOTIFY_OK;

}

 

这上面一串函数是什么意思?这里要学一个新知识——通知链技术。我们知道内核一些驱动或文件系统是被编译成模块了的,当某个模块的某些事件对其模块是很有用的,则本模块应该定义一个通知链,并导出接口。

 

那么其它模块对其事件感兴趣时,可以调用这些接口注册(注销)当事件发生时的行为。而本模块在事件发生时,调用通知其链上的所有订阅者(调用其函数)。

 

而这个notifier_block就是通知链中的元素,记录了当发出通知时,应该执行的操作(即回调函数)。这里tick_notifier是一个时钟事件监听器模块,当发出通知是,就执行tick_notify函数。

 

所以,clockevents_register_notifier函数就调用raw_notifier_chain_register来注册,其实就是把三步:获得自旋锁、把tick_notifier加入clockevents_chain、释放自旋锁。

你可能感兴趣的:(timer,struct)