跟着简叔学的,可以B站搜索 简说linux
1.软中断一般是哪些
硬件中断往往处理简单的操作,触发由外设发出。一般申请内存,保存数据一般由(底半部)来实现,在内核中有三种底半部BH,软中断、tasklet ,工作队列。工作队列是一个内核的线程,tasklet是基于软中断来实现。对于软中断来说,处理函数是可以同时运行在多个cpu之上,tasklet只能运行在唯一一个cpu上。
内核中定义了几种常用的软中断 /kernel/softirq.c1
2
3
4
5
6
7
8
9
10
11
12
13
14//软中断处理函数
struct softirq_action
{
void (*action)(struct softirq_action *);
};
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
const char * const softirq_to_name[NR_SOFTIRQS] = {
"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "IRQ_POLL",
"TASKLET", "SCHED", "HRTIMER", "RCU"
};
2.软中断的使用
软中断的使用可以分为3步,软中断的注册,触发,与执行
2.1软中断的注册
其实就是给第nr个软中断的操作设为 action
1 | void open_softirq(int nr, void (*action)(struct softirq_action *)) |
很多地方都用到了软中断的注册。
在软中断的初始化环节,注册了两个软中断,tasklet与Hi
1 | void __init softirq_init(void) |
2.2软中断的触发
1 | void raise_softirq(unsigned int nr) |
层层寻找下去之后,会有一个软件中断寄存器结构的定义。每个外设都会有一个硬件中断寄存器,硬件寄存器中每一个bit都代表着某一类型的硬件设备中断。对于软件中断来讲,也会有不同类型的软件中断,那么同理。软件中断寄存器也会将某一位置一从而判断哪一个类型的软件中断类型被触发。触发软中断时,会将中断号放到触发中断的cpu的软件寄存器里边。
2.3软中断的执行
2.3.1执行时机
2.3.1.1 ksoftirqd线程
软中断初始化时候回调用,spawn_ksoftirqd
,创建一个线程,每个cpu都会创建这个线程。
去看看 run_ksoftirqd具体执行了什么
首先有一个中断打开的动作,执行软中断时候必须要打开中断。然后local_softirq_pending()
可以判断软中段的发生,然后由__do_softirq()执行中断处理的逻辑。
2.3.1.2 硬件中断返回irq_exit()
kernel/softirq.c
ivoke_softirq
会处理cpu上面待处理的软中断,
最终会调用 __do_softirq. 也就是最终的
2.3.1.3 直接调用,例如在网络子系统等
找到最后也是直接调用 _do_softirq,所以说都是调用 _do_softirq函数。
2.3.2执行过程
执行过程就是上文说的_do_softirq
函数,如何保证触发软中断的cpu也去执行这个中断处理,如果实现中断优先级,
kernel/softirq.c
1 | asmlinkage __visible void __softirq_entry __do_softirq(void) |
那么软中断是可以被硬中断打断执行的,比如我们在软执行的时候,突然又来了硬件中断。,开始执行硬件中断。