包括/linux/interrupt.h
/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
frequency threaded job scheduling. For almost all the purposes
tasklets are more than enough. F.e. all serial device BHs et
al. should be converted to tasklets, not to softirqs.
*/
enum
{
HI_SOFTIRQ=0, /* High Priority */
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
BLOCK_IOPOLL_SOFTIRQ,
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ,
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
NR_SOFTIRQS
};
softirq
和之间的主要区别tasklet
是:
分配
- Softirq 是在编译时静态分配的。与 tasklet 不同,您不能动态注册和销毁软中断。
- Tasklet 可以使用静态分配
DECLARE_TASKLET(name, func, data)
,也可以动态分配并在运行时使用初始化tasklet_init(name, func, data)
并发
- Softirqs 可以在多个 CPU 上同时运行,即使它们属于同一类型,因为 softirqs 是
reentrant
函数,并且必须使用自旋锁显式保护它们的数据结构。
- Tasklet 是
non-reentrant
和相同类型的 tasklet 总是被序列化的:换句话说,相同类型的 tasklet 不能被两个 CPU 同时执行。但是,不同类型的 tasklet 可以在多个 CPU 上同时执行。
加工
- 软中断通过
raise_softirq()
. 待处理的软中断在被启用或被启用do_softirq()
后由ksoftirqd
内核线程处理local_bh_enable()
spin_unlock_bh()
- Tasklet 是建立在 softirq 之上的下半部分机制,即 tasklet 由两个 softirq 表示:
HI_SOFTIRQ
和TASKLET_SOFTIRQ
. Tasklet 实际上是从 softirq 运行的。这些类型中唯一真正的区别是HI_SOFTIRQ
基于 tasklet 的 tasklet 在 tasklet 之前运行TASKLET_SOFTIRQ
。所以,tasklet_schedule()
基本上打电话raise_softirq(TASKLET_SOFTIRQ)
- 请注意,软中断(以及因此的小任务和计时器)在从硬件中断返回或从系统调用返回时运行。同样,只要引发 softirq 的线程结束,就会运行单个 softirq(以及其他)以最小化
softirq latency
.