ILD

softirq
作者:YUAN JIANPENG 邮箱:yuanjp@hust.edu.cn
发布时间:2018-8-10 站点:Inside Linux Development

下半部的历史:

下半部机制状态
BH在2.5中移除
任务队列 task queues在2.5中移除
软中断 softirq从2.3开始引入
tasklet从2.3开始引入
工作队列 work queue从2.5开始引入


软中断

软中断是在编译期间静态分配的。


软中断由下述结构体表示,定义在<linux/interrupt.h>中:

1
2
3
struct softirq_action {
    void (*action)(struct softirq_action *);
};


kernel/softirq.c 中定义了一个32个软中断的数组:

1
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;


一个软中断不会抢占另一个软中断,唯一可以抢占软中断的是硬中断。不过,其它中断(甚至是相同类型的中断)可以在其它处理器上同时执行。


软中断必须被标记才会被执行,这被称作触发软中断(raising the softirq)。在下列地方,待处理的软中断会被检查和执行:


目前使用了9种软中断,如下:

ID优先级描述
HI_SOFTIRQ0优先级高的tasklet
TIMER_SOFTIRQ1定时器的下半部
NET_TX_SOFTIRQ2发送网络数据包
NET_RX_SOFTIRQ3j接收网络数据包
BLOCK_SOFTIRQ4BLOCK装置
TASKLET_SOFTIRQ5正常优先级的tasklet
SCHED_SOFTIRQ6调度程序
HRTIMER_SOFTIRQ7高分辨率定时器
RCU_SOFTIRQ8RCU锁定


注册处理程序:

1
open_softirq(NET_TX_SOFTIRQ, net_tx_action);


触发软中断

1
raise_softirq(NET_TX_SOFTIRQ);

上述接口会在禁止中断的情况下修改当前CPU的软中断raise标志。如果不是在中断中raise,将唤醒ksoftirqd线程处理软中断。


ksoftirqd

在中断返回的时候,内核会检查并处理所有的软中断,但是那些不在中断中raise的softirq,由每CPU内核ksoftirqd线程负责执行。


在下半部之间加锁

记住:下半部可能在任何时候执行。


禁止下半部

一般禁止下半部是不安全的,通常的做法是先获得一个锁,然后在禁止下半部。如果是编写内核核心代码,可能仅需要禁止下半部。

1
2
void local_bh_disable()
void local_bh_enable()

它们实际也是修改preempt_count,不过softirq使用preempt_count的0xff00掩码表示的位段。因此上述两个函数可以嵌套执行。

在local_bh_enable的时候,会检查是否在中断上上文,是否有pending的软中断,并执行软中断。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.