软中断总结

1.为什么要有软中断
   中断处理一般可以分为两个部分,一是必须及时处理的,例如收包时要及时将收到的包放入缓冲区,否则会丢失;另一类是对实时性要求不那么高的,例如从缓冲区取出数据包,送给高层协议进行处理。在中断处理中一般是要关闭中断的,因此如果中断处理占用时间很长,就有可能造成无法及时处理其他的中断,而造成丢包。
   为了解决这个问题,引入了软中断的概念。必须要及时处理的事情在中断处理中进行,而后续处理在软中断中进行(软中断是可以被抢占的)。

 

2.注册软中断
   使用open_softirq注册中断处理函数。

void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
{
 softirq_vec[nr].data = data;
 softirq_vec[nr].action = action;
}


3.设置软中断
   相关的函数:
void fastcall raise_softirq(unsigned int nr)
{
 unsigned long flags;

 local_irq_save(flags);
 raise_softirq_irqoff(nr);
 local_irq_restore(flags);
}

inline fastcall void raise_softirq_irqoff(unsigned int nr)
{
 __raise_softirq_irqoff(nr);

 if (!in_interrupt())
  wakeup_softirqd();
}

#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
可以看出__raise_softirq_irqoff就是设置了一个标志位,此后在__do_softirq中检查该标志位,并执行注册的函数。

 

4.软中断的执行
asmlinkage void do_softirq(void)
{
 __u32 pending;
 unsigned long flags;

 if (in_interrupt())
  return;

 local_irq_save(flags);

 pending = local_softirq_pending();

 if (pending)
  __do_softirq();

 local_irq_restore(flags);
}

可以看出,当处于中断上下文时,不会执行软中断。否则取得当前设置的softirq的bitmap,如果存在需要处理的软中断,则调用__do_softirq处理。下面再看看__do_softirq:

asmlinkage void __do_softirq(void)
{
 struct softirq_action *h;
 __u32 pending;
 int max_restart = MAX_SOFTIRQ_RESTART;
 int cpu;

 pending = local_softirq_pending();
 account_system_vtime(current);

 __local_bh_disable((unsigned long)__builtin_return_address(0));
 trace_softirq_enter();

 cpu = smp_processor_id();
restart:
 /* Reset the pending bitmask before enabling irqs */
 set_softirq_pending(0);

 local_irq_enable();

 h = softirq_vec;

 do {
  if (pending & 1) {
   h->action(h);
   rcu_bh_qsctr_inc(cpu);
  }
  h++;
  pending >>= 1;
 } while (pending);

 local_irq_disable();

 pending = local_softirq_pending();
 if (pending && --max_restart)
  goto restart;

 if (pending)
  wakeup_softirqd();

 trace_softirq_exit();

 account_system_vtime(current);
 _local_bh_enable();
}

可以看出,该函数会取得当前softirq的bitmask,之后设置pending为0,之后执行处理函数。在处理期间,可能有其他的软中断进行了设置,所以处理完pending后还要再次取得当前的bitmask,如果存在软中断,并且未达到执行限额MAX_SOFTIRQ_RESTART;,则继续处理软中断。

 

5.关于ksoftirqd内核线程。

  之所以要有该内核线程,是因为软中断的优先级高于用户进程,如果软中断执行过多,会造成用户进程无法执行。因此引入了ksoftirqd线程,它的优先级为最低的19。细节就不看了,总之里面会调用do_softirq处理中断。

 

6.关于软中断的执行时间

  在处理中断的do_irq的最后有irq_exit函数,在中断处理完后接着处理软中断。
void irq_exit(void)
{
 account_system_vtime(current);
 trace_hardirq_exit();
 sub_preempt_count(IRQ_EXIT_OFFSET);
 if (!in_interrupt() && local_softirq_pending())
  invoke_softirq();
 preempt_enable_no_resched();
}
其中会检查是否要处理软中断,如果需要则调用invoke_sofirq,其实就是do_softirq或者__do_softirq。
此外在local_bh_enable中也会调用do_softirq,他的作用是开启bottom half处理(softirq或tasklet),并处理需要处理的softirq。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值