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);
}
对于bh的32个tasklet_struct,调用tasklet_init以后,它们的函数指针func全部指向bh_action()函数,也就是建立了bh的执行机制,但具体的bh函数还没有与之挂勾,就像具体的中断服务例程还没有挂入中断服务队列一样。同样,调用open_softirq()以后,软中断TASKLET_SOFTIRQ的服务例程为tasklet_action(),而软中断HI_SOFTIRQ的服务例程为tasklet_hi_action()。
3.Bh的初始化
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中,在该队列中排队等待。