软中断与Bottom Half


中断服务一般都是在将中断请求关闭的条件下执行的,以避免嵌套而使控制复杂化。可是,如果关中断的时间持续太长就可能因为CPU不能及时响应其他的中断请求而使中断(请求)丢失,为此,内核允许再将具体的中断服务程序挂入到中断请求队列时将SA_INTERRUPT标志置成0,使这个中断服务程序在开中的条件下执行。实际情况下,全开中断与不开中断都有弊端。

一般,一次中断服务的过程常常可以分成两部分。开头的部分往往必须在关中断的情况下执行,这部分时间性又往往很强(在一定时间内完成),而且相继的几次中断请求不能合并在一起执行。而后部分往往在开中下执行,这些操作往往允许延迟一段后执行。而且有可能将多次中断服务中相关部分合并在一起处理。后半部分就成为“bottom half”,缩写bh。

在linux2.3.43之前的版本中,内核中设置了一个函数指针数组bh_base[ ],其大小为32,数组中的每个指针都用来指向一个具体的bh函数,又设置了两个32位无符号整数bh_active和bh_mask,每个无符号整数中32位对应着数组bh_base[ ]中的32个元素。具体的bh函数通过init_bh()设置。

bh_active相当于“中断请求寄存器”,bh_mask相当于“中断屏蔽寄存器”,当需要执行一个bh函数时,就通过mark_bh()函数将bh_active的某一位设成1,相当于中断源发出中断请求。如果相当于“中断屏蔽寄存器”的bh_mask中的相应位也是1,即系统允许执行这个bh函数,那么就会在每次执行完do_IRQ()中断服务程序后,以及每次系统调用结束之时,在do_bottom_half()中执行相应的bh函数

do_bottom_half()中,把bh函数的执行严格的“串行化”了。一方面,bh函数的执行不允许嵌套;为此,在do_bottom_half中针对同一CPU的嵌套执行加了锁。另一方面,在多CPU系统中,在同一时间内最多允许一个CPU执行bh函数,为此在do_bottom_half()中针对不同CPU同时执行bh函数也加了锁。第二种情况使bh情况“完全串行化”,对于多CPU情况,效率低下。因此有添加了其他几种机制,并把他们纳入一个统一的框架中,这就是“软中断”(softirq)机制。

软中断机制

软中断本身是一种机制,同时也是一个框架。在这个框架里有bh机制(设计保守,安全,简单的软中断)。

系统在初始化时通过函数softirq_init( )对内核的软中断机制进行初始化。对TAKLET_SOFTIRQ和HI_SOFTIRQ两种软中断进行初始化。内核中为bh机制设置了一个结构数组bh_task_vec[ ],这是tasklet_struct数据结构的数组。

struct tasklet_struct
{
/**
 * 指向下一个描述符
 */
struct tasklet_struct *next;
/**
 * tasklet的状态。
 * 
 */
unsigned long state;
/**
 * 锁计数器。
 */
atomic_t count;
/**
 * tasklet功能函数
 */
void (*func)(unsigned long);
/**
 * 传给功能函数的参数。
 */
unsigned long data;
};

tasklet是“多序”的,允许在不同的CPU上同时执行不同的tasklet。func全部指向bh_action()。

对其他软中断的初始化是通过open_softirq()完成的。

内核中为软中断设置了一个以“软中断号”为下标的数组softirq_vec[ ],是全局变量。系统中的各个CPU所看到的是同一个数组。但是,每个CPU各有其自己的“软中断控制/状况结构”,所以形成了一个以CPU编号为下标的数组irq_stat[ ]。各个CPU可以按其自身的编号访问相应的数据结构。

内核中还有另一个以CPU编号为下标的数组tasklet_hi_vec[ ],这是tasklet_head结构数组,每个tasklet_head结构就是一个tasklet_struct结构的对列头。


需要执行一个特定的bh函数时,可以通过inline函数mark_bh()请求,然后以bh函数的编号为下标在bh_task_vec[ ]中,就可以找到相应的tasklet_struct数据结构,然后用其调用tasklet_hi_schedule(),在tasklet_hi_schedule()函数中找到该CPU的对列头,并把tasklet_struct链入这个队列,其中同时设置了TAKLET_STATE_SCHED防止同一个tasklet_struct重复链入。

内核每当在do_IRQ()中执行完一个通道中的中断服务程序以后,以及每当从系统调用返回时,都要检查是否有中断请求在等待执行。(检查softirq_active和softirq_mask) ---》检测到软中断后,就要通过do_softirq( )加以执行。执行的服务程序为bh_action()。

软中断服务程序既不允许在一个硬中断服务程序内部执行,也不允许在一个软中断服务程序内部执行。所以通过宏操作in_interrupt()加以检测,该检测防止了软中断服务程序的嵌套。
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值