我正在阅读Linux Kernel Development并且对互斥量和信号量之间的差异感到困惑。
作者说:
中断处理程序或下半部分无法获取互斥锁
我知道互斥锁可能会导致睡眠,并且中断处理程序未在任何特定的进程上下文中运行,因此不允许使用互斥锁或信号量。但是下半部分可以通过工作队列实现并且可以休眠。
那么,为什么不能在下半部分获取互斥锁呢?这里关注的是简单性和效率还是其他?
我正在阅读Linux Kernel Development并且对互斥量和信号量之间的差异感到困惑。
作者说:
中断处理程序或下半部分无法获取互斥锁
我知道互斥锁可能会导致睡眠,并且中断处理程序未在任何特定的进程上下文中运行,因此不允许使用互斥锁或信号量。但是下半部分可以通过工作队列实现并且可以休眠。
那么,为什么不能在下半部分获取互斥锁呢?这里关注的是简单性和效率还是其他?
互斥锁/信号量锁定可以休眠,但 BH 被设计为不休眠。Softirq 在许多地方被异步检查执行。例如,它们可以在您每次恢复 BH 时执行(如 spin_unlock_bh)。使此类代码在互斥锁上休眠是一个非常糟糕的主意。如果您在持有 BH 自旋锁的同时休眠,您可能会导致其他 BH 代码休眠,甚至可能使整个系统死锁。
从这个角度来看,工作队列不被认为是 BH,它们在可以自由休眠的内核线程的上下文中运行。因此,互斥锁适用于工作队列,但不适用于小任务。
BH 是一个模糊的术语,我发现将 linux 内核视为具有三个执行上下文会很有帮助:用户(包括内核线程)、softirq 和 hardirq。这些中的每一个的抢占可以通过 preempt_count 中的一组位来控制。
创建互斥锁的主要动机是简单和高效。由于下半部分的同步可能很复杂,因此建议在下半部分避免互斥锁。下半部分的设计不适合互斥体。例如。互斥锁应该在相同的上下文中被锁定/解锁- 这在下半部分的情况下很难遵循。
从理论上讲,您可以决定实施不同的整个中断处理,其中使用互斥锁是合理的。就像“线程”中断处理程序一样。http://lwn.net/Articles/380931/