中断底半部:softirq、tasklet、workqueue

为了在中断执行时间尽可能短和中断处理需完成大量工作之间找到一个平衡点,Linux 将中断处理程序分解为两个半部:顶半部(top  half)和底半部(bottom half)。

顶半部完成尽可能少的比较紧急的功能,它往往只是简单地读取寄存器中的中断状态并清除中断标志后就进行“登记中断”的工作。“登记中断”意味着将底半部处理程序挂到该设备的底半部执行队列中去。这样,顶半部执行的速度就会很快,可以服务更多的中断请求。

现在,中断处理工作的重心就落在了底半部的头上,它来完成中断事件的绝大多数任务。底半部几乎做了中断处理程序所有的事情,而且可以被新的中断打断,这也是底半部和顶半部的最大不同,因为顶半部往往被设计成不可中断。底半部则相对来说并不是非常紧急的,而且相对比较耗时,不在硬件中断服务程序中执行。

a. 底半部可以被新的中断事件打断,这是和顶半部最大的不同,顶半部通常被设计成不可被打断。

b. 底半部相对来说不是非常紧急的,而且相对比较耗时,不在硬件中断服务程序中执行。

c. 如果中断要处理的工作本身很少,所有的工作可在顶半部全部完成。

尽管顶半部、底半部的结合能够改善系统的响应能力,但是,僵化地认为 Linux设备驱动中的中断处理一定要分两个半部则是不对的。如果中断要处理的工作本身很少,则完全可以直接在顶半部全部完成。

1. 软中断(softirq)

软中断(softirq)也是一种传统的底半部处理机制,它的执行时机通常是顶半部返回的时候,tasklet的基于软中断实现的,因此也运行于软中断上下文。

软中断支持SMP,同一个softirq可以在不同的CPU上同时运行,softirq必须是可重入的。软中断是在编译期间静态分配的,它不像tasklet那样能被动态的注册或去除。

软中断和tasklet都是运行在中断上下文中,它们与任一进程无关,没有支持的进程完成重新调度。所以软中断和tasklet不能睡眠、不能阻塞,它们的代码中不能含有导致睡眠的动作,如减少信号量、从用户空间拷贝数据或手工分配内存等。也正是由于它们运行在中断上下文中,所以它们在同一个CPU上的执行是串行的,这样就不利于实时多媒体任务的优先处理。

软中断的特性:

1).一个软中断不会抢占另外一个软中断。

2).唯一可以抢占软中断的是中断处理程序。

3).其他软中断(包括相同类型的)可以在其他的处理其上同时执行。

4).一个注册的软中断必须在被标记后才能执行。

5).软中断不可以自己休眠(即调用可阻塞的函数或sleep等)。

6).索引号小的软中断在索引号大的软中断之前执行

2. tasklet

他的执行上下文是软中断,执行时机通常是顶半部返回的时候。 

tasklet是一种特殊的软中断,同一时刻一个tasklet只能在一个CPU 执行,不同的tasklet可以在不同的CPU上执行。这和软中断不同,软中断同一时刻可以在不同的CPU并行执行,因此软中断必须考虑重入的问题。

引入tasklet,最主要的是考虑支持SMP,提高SMP多个cpu的利用率;两个相同的tasklet决不会同时执行。tasklet可以理解为softirq的派生,所以它的调度时机和软中断一样。对于内核中需要延迟执行的多数任务都可以用tasklet来完成,由于同类tasklet本身已经进行了同步保护,所以使用tasklet比软中断要简单的多,而且效率也不错。tasklet把任务延迟到安全时间执行的一种方式,在中断期间运行,即使被调度多次,tasklet也只运行一次,不过tasklet可以在SMP系统上和其他不同的tasklet并行运行。在SMP系统上,tasklet还被确保在第一个调度它的CPU上运行,因为这样可以提供更好的高速缓存行为,从而提高性能。

tasklet的特性:.不允许两个两个相同类型的tasklet同时执行,即使在不同的处理器上。

3. 工作队列(workqueue)

工作队列的执行上下文是内核线程,因此可以调度和睡眠。

如果推后执行的任务需要睡眠,那么就选择工作队列。另外,如果需要用一个可以重新调度的实体来执行你的下半部处理,也应该使用工作队列。它是唯一能在进程上下文运行的下半部实现的机制,也只有它才可以睡眠。这意味着在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,它都会非常有用。

work queue造成的开销最大,因为它要涉及到内核线程甚至是上下文切换。这并不是说work queue的低效,但每秒钟有数千次中断,就像网络子系统时常经历的那样,那么采用其他的机制可能更合适一些。 尽管如此,针对大部分情况工作队列都能提供足够的支持。

工作队列特性:

1).工作队列会在进程上下文中执行

2).可以阻塞。(前两种机制是不可以阻塞的)

3).可以被重新调度。(前两种只可以被中断处理程序打断)

4).使用工作队列的两种形式:

     1>缺省工作者线程(works threads)

     2>自建的工作者线程

5).在工作队列和内核其他部分之间使用锁机制就像在其他的进程上下文一样。

6).默认允许响应中断。        

4. 硬中断、软中断的区别

硬中断是外部设备低CPU的中断,软中断是中断底半部的一种处理机制。

中断优先级>软中断>任何线程。

发布了170 篇原创文章 · 获赞 116 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/u012247418/article/details/104179984