3.5.4 软中断、bhtasklet的初始化

1.Tasklet的初始化

Tasklet的初始化是由tasklet_ init()函数完成的:

 void tasklet_init(struct tasklet_struct *t,

                   void (*func)(unsigned long), unsigned long data)

{

         t->next = NULL;

         t->state = 0;

         atomic_set(&t->count, 0);

         t->func = func;

         t->data = data;

}

 其中,atomic_set()为原子操作,它把t->count置为0

2.软中断的初始化

  首先通过open_softirq()函数打开软中断:

   void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)

{

         softirq_vec[nr].data = data;

         softirq_vec[nr].action = action;

 

 然后,通过softirq_init()函数对软中断进行初始化:

void __init softirq_init()

{

         int i;

 

         for (i=0; i<32; i++)

                tasklet_init(bh_task_vec+i, bh_action, i);

 

         open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL);

         open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);

}

    对于bh32tasklet_struct,调用tasklet_init以后,它们的函数指针func全部指向bh_action()函数,也就是建立了bh的执行机制,但具体的bh函数还没有与之挂勾,就像具体的中断服务例程还没有挂入中断服务队列一样。同样,调用open_softirq()以后,软中断TASKLET_SOFTIRQ的服务例程为tasklet_action(),而软中断HI_SOFTIRQ的服务例程为tasklet_hi_action()。

3Bh的初始化

     bh的初始化是由init_bh()完成的:

void init_bh(int nr, void (*routine)(void))

{

         bh_base[nr] = routine;

         mb();

 }

  这里调用的函数mb()CPU中执行指令的流水线有关,我们对此不进行进一步讨论。下面看一下几个具体bh的初始化(在kernel/sched.c中):

  init_bh(TIMER_BH,timer_bh);

  init_bh(TUEUE_BH,tqueue_bh);

  init_bh(IMMEDIATE_BH,immediate_bh);

     初始化以后,bh_base[TIMER_BH]处理定时器队列timer_bh,每个时钟中断都会激活TIMER_BH,在第五章将会看到,这意味着大约每隔10ms这个队列运行一次。bh_base[TUEUE_BH]处理周期性的任务队列tqueue_bh,而bh_base[IMMEDIATE_BH]通常被驱动程序所调用,请求某个设备服务的内核函数可以链接到IMMEDIATE_BH所管理的队列immediate_bh中,在该队列中排队等待。