1、软中断介绍
Linux 内核使用结构体 softirq_action 表示软中断, softirq_action结构体定义在文件include/linux/interrupt.h 中,内容如下:
在 kernel/softirq.c 文件中一共定义了 10 个软中断:
static struct softirq_action softirq_vec[NR_SOFTIRQS];
中断 | 含义 |
---|---|
HI_SOFTIRQ=0 | 高优先级软中断 |
TIMER_SOFTIRQ | 定时器软中断 |
NET_TX_SOFTIRQ | 网络数据发送软中断 |
NET_RX_SOFTIRQ | 网络数据接收软中断 |
BLOCK_SOFTIRQ | 块设备的软中断 |
BLOCK_IOPOLL_SOFTIRQ | 支持IO轮询的块设备软中断 |
TASKLET_SOFTIRQ | tasklet 软中断 |
SCHED_SOFTIRQ | 调度软中断 |
HRTIMER_SOFTIRQ | 高精度定时器软中断 |
RCU_SOFTIRQ | RCU 软中断 |
NR_SOFTIRQS | 软中断数,为10 |
一共有 10 个软中断,因此 NR_SOFTIRQS 为 10,因此数组 softirq_vec 有 10 个元素。 softirq_action 结构体中的 action 成员变量就是软中断的服务函数,数组 softirq_vec 是个全局数组,因此所有的 CPU(对于 SMP 系统而言)都可以访问到,每个 CPU 都有自己的触发和控制机制,并且只执行自己所触发的软中断。但是各个 CPU 所执行的软中断服务函数确是相同的,都是数组 softirq_vec 中定义的 action 函数。
2、软中断的使用
2.1、注册软中断处理函数
使用 open_softirq 函数注册对应的软中断处理函数:
void open_softirq(int nr, void (*action)(struct softirq_action *))
参数及其含义:
参数 | 含义 |
---|---|
nr | 要开启的软中断,在上面10个中选一个 |
action | 软中断对应的处理函数 |
2.2、触发软中断
注册好软中断以后需要通过 raise_softirq 函数触发, raise_softirq 函数原型如下:
void raise_softirq(unsigned int nr)
参数 | 含义 |
---|---|
nr | 要开启的软中断,在上面10个中选一个 |
软中断必须在编译的时候静态注册! Linux 内核使用 softirq_init 函数初始化软中断,softirq_init 函数定义在 kernel/softirq.c 文件里面,函数内容如下:
void __init softirq_init(void)
{
int cpu;
for_each_possible_cpu(cpu)
{
per_cpu(tasklet_vec, cpu).tail =
&per_cpu(tasklet_vec, cpu).head;
per_cpu(tasklet_hi_vec, cpu).tail =
&per_cpu(tasklet_hi_vec, cpu).head;
}
open_softirq(TASKLET_SOFTIRQ, tasklet_action);
open_softirq(HI_SOFTIRQ, tasklet_hi_action);
}
softirq_init 函数默认会打开 TASKLET_SOFTIRQ 和HI_SOFTIRQ。