Linux内核中的软中断、tasklet和工作队列详解
本文主要介绍Linux内核中的软中断、tasklet和工作队列详解:
首先,先介绍一下中断上下文以及进程上下文:
所谓上下文就是中断或进程发生时前后的环境。中断上下文就是当中断产生后,将中断前的参数或函数入口等参数保存到临时寄存器中,也就是我们常说的保护现场或中断上文,然后进入中断向量表中查找跳转或执行的中断,到恢复现场可以统称为中断下文,我的理解就是这样。
而进程上下文就是进程在执行的过程中,由于CPU调度的关系转去执行其他的进程时,需要保护或保存的环境或变量。有些文章将其分为:进程上,进程中,进程下。对应过去,当前以及未来。
通常我们将中断分为上半部与下半部,两者最主要的区别就是:是否能够接收延迟响应的问题。比如说:在网络传输中,网卡接收到数据包这个事件不一定需要马上被处理,适合用下半部去实现;但是用户敲击键盘这样的事件就必须马上被响应,应该用上半部中断实现。
- 如果一个任务对时间非常敏感,将其放在中断处理程序中执行。
- 如果一个任务和硬件相关,将其放在中断处理程序中执行。
- 如果一个任务要保证不被其他中断(特别是相同的中断)打断,将其放在中断处理程序中执行。
- 其他所有任务,考虑放在下半部去执行。
有写内核任务需要延后执行,因此才有的下半部,进而实现了三种实现下半部的方法。这就是本文要讨论的软中断、tasklet和工作队列。
下表可以更直观的看到它们之间的关系。
软中断
- 软中断作为下半部机制的代表,是随着SMP(share memory processor)的出现应运而生的,它也是tasklet实现的基础(tasklet实际上只是在软中断的基础上添加了一定的机制)。软中断一般是“可延迟函数”的总称,有时候也包括了tasklet(请读者在遇到的时候根据上下文推断是否包含tasklet)。它的出现就是因为要满足上面所提出的上半部和下半部的区别,使得对时间不敏感的任务延后执行,而且可以在多个CPU上并行执行,使得总的系统效率可以更高。它的特性包括:
- 产生后并不是马上可以执行,必须要等待内核的调度才能执行。软中断不能被自己打断(即单个cpu上软中断不能嵌套执行),只能被硬件中断打断(上半部)。
- 可以并发运行在多个CPU上(即使同一类型的也可以)。所以软中断必须设计为可重入的函数(允许多个CPU同时操作),因此也需要使用自旋锁来保其数据结构