bottom half执行

来源:互联网 发布:通联数据发展前景 编辑:程序博客网 时间:2024/05/12 03:22

Linux的内核中断分为两部分,第一部分的执行一般是在关中断的情况下执行的,第二部分是在开中断的情形下。一般要求中断程序的第一部分尽可能的短,如果关中断太久,会使PC的忽略了很多中断。因此一般把对时间要求高和与硬件打交道的代码安排在中断程序的第一部分,而其他对时间要求比较不高的代码安排在第二部分。这是为什么内核的中断程序要分两部分的原因。本文重点介绍,内核的中断程序的第二部分是怎么完成的,即内核中断程序第二部分的机制。

首先,中断程序的第二部分一般会在完成每个中断的第一部分后,开中断后,检查每个CPU的irq_cpustat_t结构中的__softirq_active是否置位,如果有就应该执行中断的第二部分。另外在每次系统调用返回时,也会检查该标志。因此中断的第二部分,一般在这两种情况下,执行。在执行中断的第二部分,允许被中断的第一部分打断,但不允许被第二部分打断。即不能第二部分中断嵌套第二部分。

在arch/i386/kernel/irq.c中 

625   if (softirq_active(cpu) & softirq_mask(cpu))                                     
 626     do_softirq();

此时,就进入了中断程序第二部分的执行。/

do_softirq()的内容如下:我们就在代码中直接解释

50 asmlinkage void do_softirq()
 51 {
 52   int cpu = smp_processor_id();//这个函数取得当前CPU的标号,这个在多CPU中使用
 53   __u32 active, mask;
 54
 55   if (in_interrupt())//如果本中断是中断一个执行第二部分中断的程序或者已经在第一部分中断中,则返回,不允许第二部分中断嵌套
 56     return;
 57
 58   local_bh_disable();关第二部分中断设置了irq_cpustat_t的__local_bh_count,即不允许再执行do_softirq()
 59
 60   local_irq_disable();//关硬件中断
 61   mask = softirq_mask(cpu);//取当前CPU的允许允许的第二部分中断类型
 62   active = softirq_active(cpu) & mask;//取当前挂起的中断,即要执行的中断
 63
 64   if (active) {//如果是0,即没有要执行的第二部分中断,非0则执行
 65     struct softirq_action *h;
 66
 67 restart:
 68     /* Reset active bitmask before enabling irqs */
 69     softirq_active(cpu) &= ~active;//对CPU的irq_cpustat_t结构中的__softirq_active清0
 70
 71     local_irq_enable();//开硬件中断
 72
 73     h = softirq_vec;//设置h为struct softirq_action softirq_vec[32] __cacheline_aligned;的头部

/*对softirq_vec解释

 68 struct softirq_action                                                               
 69 {
 70   void  (*action)(struct softirq_action *);
 71   void  *data;
 72 };

 

这个结构中包含一个函数指针和一个值.这个结构会在softirq_init()中调用open_softirq()中初始化,0号为tasklet_action,4号为tasklet_hi_action,这两个函数,这两个函数会从对应的数据结构struct tasklet_head tasklet_vec[NR_CPUS]和struct tasklet_head tasklet_hi_vec[NR_CPUS]中取一个个的tasklet_struct执行相应中断第二部分函数。

 

 待续...

 

 

*/
 74     mask &= ~active;
 75
 76     do {
 77       if (active & 1)
 78         h->action(h);
 79       h++;
 80       active >>= 1;
 81     } while (active);
 82
 83     local_irq_disable();
 84
 85     active = softirq_active(cpu);
 86     if ((active &= mask) != 0)
 87       goto retry; 

88   }
 89
 90   local_bh_enable();
 91
 92   /* Leave with locally disabled hard irqs. It is critical to close
 93    * window for infinite recursion, while we help local bh count,
 94    * it protected us. Now we are defenceless.
 95    */
 96   return;
 97
 98   retry:
 99   goto restart;
100 }