Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1686011
  • 博文数量: 511
  • 博客积分: 967
  • 博客等级: 准尉
  • 技术积分: 2560
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-06 14:19
文章分类

全部博文(511)

文章存档

2016年(11)

2015年(61)

2014年(257)

2013年(63)

2012年(119)

分类: LINUX

2014-05-17 22:39:08

本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
    


在Linux kernel中,软中断在同一个CPU上,只能有一个运行实例。本文主要讲解Linux kernel是如何实现这个软中断特征的。

所有的软中断处理函数都是由do_softirq->__do_softirq调用的。所有只要保证一个CPU上只可能运行一个do_softirq实例,就保证了软中断只可能在同一CPU上存在一个实例。

在__do_softirq中,会调用__local_bh_disable去disable 软中断
  1. static inline void __local_bh_disable(unsigned long ip)
  2. {
  3.     add_preempt_count(SOFTIRQ_OFFSET);
  4.     barrier();
  5. }
该函数的实现是增加current_thread_info()->preempt_count的软中断部分的计数。
通过增加这个计数,保证了该进程不会被调度出去,那么软中断的执行序列一般就不会被打断,可以线性执行,也就保证了一个软中断的实例。但是如果发生中断,就会打断当前的软中断。而中断函数返回时,也是软中断的一个调用点。

我们来看看kernel是如何处理这种情况的。
  1. void irq_exit(void)
  2. {
  3.     ...... ......
  4.     if (!in_interrupt() && local_softirq_pending())
  5.         invoke_softirq();
     ...... ......
  1. }
这个函数是由do_irq调用的,也就是中断返回时,软中断的调用点。只有在in_interrupt()返回为假且有pending的软中断时,才会调用软中断。

看in_interrupt的实现。
  1. #define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \
  2.                  | NMI_MASK))


  3. #define in_interrupt()        (irq_count())
而在__do_softirq增加了preempt_count软中断部分的计数,这样就避免了在运行软中断处理函数时,发生了硬中断从而再次调用软中断的问题。

其实在软中断函数do_softirq的入口也有类似的判断
  1. asmlinkage void do_softirq(void)
  2. {
  3.     __u32 pending;
  4.     unsigned long flags;
  1.     if (in_interrupt())
  2.         return;

  3.     ...... ......
  4. }
同样是通过调用in_interrupt()来检查,来保证同一CPU上只有一个软中断运行实例。

通过上面的代码,我们知道了Linux kernel如何保证同一CPU上只有一个软中断的运行实例,同时也就明白了不同CPU为什么可以有同一类型的软中断处理函数同时运行——因为preempt_count是一个进程的值,而不同CPU上是不同的进程在运行。


阅读(623) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~