软中断保留给系统中对时间要求最严格以及最重要的下半部使用。目前,只有两个子系统---网络和SCSI直接使用软中断。此外,内核定时器和taskelet都是建立在软中断上的。对于时间要求严格并能自己高效完成加锁工作的应用,软中断会是正确的选择。
怎样使用软中断呢?
1.分配索引
在编译期间,可以通过<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,
- TIMER_SOFTIRQ,
- NET_TX_SOFTIRQ,
- NET_RX_SOFTIRQ,
- BLOCK_SOFTIRQ,
- TASKLET_SOFTIRQ,
- SCHED_SOFTIRQ,
- #ifdef CONFIG_HIGH_RES_TIMERS
- HRTIMER_SOFTIRQ,
- #endif
- };
2. 注册你的处理程序
在运行时 通过调用open_softirq()注册软件处理程序,该函数有三个参数:软中断的索引号、处理函数和data域存放的数值:
- void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
- {
- softirq_vec[nr].data = data;
- softirq_vec[nr].action = action;
- }
3.触发你的软中断
通过在枚举类型的列表中添加新项,调用open_softirq()进行注册之后,新的软中断处理程序就能够运行。raise_softirq()函数可以将一个软中断设置为挂起状态,让它在下次调用do_softirq()函数时投入运行:
- void fastcall raise_softirq(unsigned int nr)
- {
- unsigned long flags;
- local_irq_save(flags);
- raise_softirq_irqoff(nr);
- local_irq_restore(flags);
- }
该函数在触发一个软中断之前先要禁止中断,触发后再恢复原来的状态,如果中断本来就已经被禁止了,那么可以调用另一个函数raise_softirq_irqoff():
- /*
- * This function must run with irqs disabled!
- */
- inline fastcall void raise_softirq_irqoff(unsigned int nr)
- {
- __raise_softirq_irqoff(nr);
- /*
- * If we're in an interrupt or softirq, we're done
- * (this also catches softirq-disabled code). We will
- * actually run the softirq once we return from
- * the irq or softirq.
- *
- * Otherwise we wake up ksoftirqd to make sure we
- * schedule the softirq soon.
- */
- if (!in_interrupt())
- wakeup_softirqd();
- }
- #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
- #define or_softirq_pending(x) or_pda(__softirq_pending, (x))
在中断处理程序中触发软中断是最常见的形式。在这种情况下,中断处理程序执行硬件设备的相关操作,然后触发相应的软中断,最后退出。内核在执行完 中断处理程序之后,马上调用do_softirq()函数,于是软中断开始执行中断处理程序留给它要完成的剩余任务。