日期:2014-05-16  浏览次数:20714 次

Linux内核探讨-- 第五章

文是个人分析《Linux内核设计与实现》而写的总结,欢迎转载,请注明出处:

                                                                              http://blog.csdn.net/dlutbrucezhang/article/details/12347097

      

      第五章--下半部和退后执行的工作

      上一篇文章提到中断分为上半部和下半部,上半部称作中断处理程序。下半部处理的则是比较耗时的工作。那么为什么会出现下半部呢?
      我们知道,中断是异步发生的,一旦CPU接收了中断,那么就必须处理,所以,就要打断当前执行的代码,如果当前执行的代码很重要,那么中断处理就不应该占据很长的时间,所以,在中断处理中把需要紧急处理的工作放在处理程序中,而把耗时的工作放在下半部执行。下半部执行的时机是不确定的,只是保证它不在当前执行就可以了,一般是放在中断处理程序返回后就会立即执行。这是出现下半部原因的第一个方面。
      中断在执行时,最好的情况是屏蔽掉它那一条中断线,可是,很不幸的事总是会发生,有些中断会使用IRQF_DISABLED标志,那么,所有的中断都会被屏蔽。如果,中断处理是一项很耗时的工作,且这时会不停的出现中断,那么用户进程就会因此而饥饿,所以,需要找个方法来应付这种情况。

      1.下半部执行的策略

      下半部的执行在Linux内核不断完善的过程中,出现了一系列方法,由于有些方法早已经被淘汰了,所以,这里仅介绍在2.6内核中出现的处理方法。
      在2.6内核中出现了三种策略。
      软中断,tasklet,工作队列
      下面,我就对这三种策略进行介绍。

      2.软中断

      这种策略最为高效,但是实际在使用中却用到的不多,因为我们需要处理同步问题,且不能在中断上下文中睡眠,所以,实现难度比较大。
      它是在内核编译期间静态指定的,存在32个软中断,但是实际用到的只有9个。
      软中断保留给系统中对时间要求最为严格以及最重要的下半部使用。
      一个注册的软中断必须被标记以后才能够得到处理,最终系统会调用 do_softirq(),执行软中断,下面,让我们来看看它的执行代码:
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);
}

      可以看到,首先它会检查软中断位图,看看哪一位会被标记,如果那一位被标记,那么它所对应的处理程序就会执行,因为位图中存在32位,所以,这段程序是循环执行的,且最多会循环32次。
      软中断允许同类型的软中断同时执行,这也是不好控制它的原因,这里牵扯到了内核同步的问题,这在以后的文章中会有所介绍。

  &nbs