何时在Linux内核中使用内核线程与工作队列

Jam*_*cks 30 linux linux-kernel

有许多方法可以在Linux内核中安排工作:定时器,tasklet,工作队列和内核线程.什么时候使用一个与另一个有什么指导方针?

有明显的因素:计时器函数和tasklet无法休眠,因此它们不能等待互斥锁,条件变量等.

在驱动程序中为我们选择哪种机制有哪些其他因素?

哪个是首选机制?

use*_*697 31

softirqs : deferred work runs in interrupt context
tasklets : deferred work runs in interrupt context
work queues : deferred work runs in process context

softirqs : cannot run simultaneously on different CPU's
tasklets : cannot run simultaneously on different CPU's
work queues : can run simultaneously on different CPU's

softirqs : cannot go to sleep
tasklets : cannot go to sleep
work queues : can go to sleep

softirqs : cannot be preempted/schedule
tasklets : cannot be preempted/schedule
work queues : maybe be preempted/schedule

softirqs : not easy to use
tasklets : easy to use
work queues : easy to use

  • 实际上,softirq是可无限扩展的,即它们可以在不同的CPU上同时运行:"Softirq可以在多个CPU上同时运行,即使它们属于同一类型.因此,softirqs是可重入的函数,必须通过旋转明确保护其数据结构锁定.相同类型的Tasklet总是被序列化:换句话说,同一类型的tasklet不能同时由两个CPU执行." 见:http://www.91kaifa.com/doc/ulk/0596005652/understandlk-chp-4-sect-7.html (12认同)
  • 编辑:序列化当然只对*相同类型*的tasklet有效."不同类型的Tasklet可以在多个CPU上同时执行." (4认同)
  • axeoth是对的.并且,自2012年8月起,工作队列中相同类型的"工作项"无法在不同的CPU上同时运行,因为工作队列现在是不可重入的:http://lwn.net/Articles/511421/ (2认同)

Mic*_*kis 29

正如你所说,这取决于手头的任务:

工作队列将工作推迟到内核线程 - 您的工作将始终在进程上下文中运行.它们是可调度的,因此可以睡觉.

通常,工作队列或sotftirqs/tasklet之间没有争论; 如果延迟工作需要休眠,则使用工作队列,否则使用softirqs或tasklet.Tasklet也更适合中断处理(它们有一定的保证,例如:一个tasklet永远不会比下一个tick更晚运行,它总是就自身而序列化等等).

当您确切知道何时发生某些事情并且不想在此期间中断/阻止进程时,内核定时器很好.它们在进程上下文之外运行,并且它们在其他代码方面也是异步的,因此如果你不小心,它们就是竞争条件的来源.

希望这可以帮助.

  • 好吧,创建工作队列背后的意图是他们会部分替换内核线程作为在内核中调度任务的方法(懒惰的工作队列是最新的处理工作),因为在某些时候,内核线程的数量是管理成本很高.考虑到这一点,我认为对于大多数意图和目的,我通常更喜欢工作队列而不是内核线程. (3认同)