中断下半部

370 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

为了避免处理复杂的中断嵌套,中断处理程序是在关闭中断的情况下执行的。可是,如果关闭中断的时间太长,可能导致中断请求丢失。例如周期时钟每隔10毫秒发送一个中断请求,如果执行某个中断处理程序花费的时间超过10毫秒,在这段时间里时钟发送了两个中断请求,但是处理器只认为收到一个时钟中断请求。

最激进的解决办法是中断线程化,但是常用的解决办法是把中断处理程序分为两部分,上半部(top half,th)在关闭中断的情况下执行,只做对时间非常敏感、与硬件相关或者不能被其他中断打断的工作;下半部(bottom half,bh)在开启中断的情况下执行,可以被其他中断打断。 上半部称为硬中断(hardirq),下半部有3种:软中断(softirq)、小任务(tasklet)和工作队列(workqueue)。3种下半部的区别如下。 (1)软中断和小任务不允许睡眠;工作队列是使用内核线程实现的,处理函数可以睡眠。

(2)软中断的种类是编译时静态定义的,在运行时不能添加或删除;小任务可以在运行时添加或删除。

(3)同一种软中断的处理函数可以在多个处理器上同时执行,处理函数必须是可以重入的,需要使用锁保护临界区;一个小任务同一时刻只能在一个处理器上执行,不要求处理函数是可以重入的。

软中断

软中断(softirq)是中断处理程序在开启中断的情况下执行的部分,可以被硬中断抢占。 内核定义了一张软中断向量表,每种软中断有一个唯一的编号,对应一个softirq_action实例,softirq_action实例的成员action是处理函数。

kernel/softirq.c
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;include/linux/interrupt.h
struct softirq_action
{
     void (*action)(struct softirq_action *);
};

软中断的种类

目前内核定义了10种软中断,各种软中断的编号如下:

(1)HI_SOFTIRQ:高优先级的小任务。

(2)TIMER_SOFTIRQ:定时器软中断。

(3)NET_TX_SOFTIRQ:网络栈发送报文的软中断。

(4)NET_RX_SOFTIRQ:网络栈接收报文的软中断。

(5)BLOCK_SOFTIRQ:块设备软中断。

(6)IRQ_POLL_SOFTIRQ:支持I/O轮询的块设备软中断。

(7)TASKLET_SOFTIRQ:低优先级的小任务。

(8)SCHED_SOFTIRQ:调度软中断,用于在处理器之间负载均衡。

(9)HRTIMER_SOFTIRQ:高精度定时器,这种软中断已经被废弃,目前在中断处理程序的上半部处理高精度定时器。

(10)RCU_SOFTIRQ:RCU软中断。

软中断的编号形成了优先级顺序,编号小的软中断优先级高。