local_bh_disable
禁用处理下半部分(softirqs)。软线程要么在中断返回路径上处理,要么由ksoftirqd(每cpu)线程处理,如果系统遭受沉重的软线程负载,该线程将被唤醒。
preempt_disable
禁用抢占,这意味着,当一个线程在preempt_disable
<-> preemt_enable
范围内执行时,它不会被调度器置于睡眠状态。这意味着,如果当前线程在该范围内时发生系统定时器中断,它可能会更新调度器的记帐表,但不会将上下文切换到另一个线程。这包括软性的。
local_irq_disable
或local_irq_save
禁用本地cpu中断。这意味着本地CPU不会对任何irqs做出反应,因此它不会运行任何中断返回路径,因此不能在那里运行软中断。
假设我上面的陈述是真的(我不确定),那么在你调用preempt_disable
和local_irq_save
(同时在进程上下文中)之后调用local_bh_disable
不是多余的吗?
是。一旦调用了local_irq_save/disable,就不需要进一步的保护了——您不会被中断(除了NMI或代码中的异常)。
然而,你经常会发现一些代码被设计成可以从不同的上下文中调用,所以它们可能为一些子操作提供保护,这些子操作最终在某些路径中是冗余的。
preempt_disable/enable作用域确保在该作用域内调用schedule不做任何事情(即禁用抢占)。但是,软请求或临时请求可能会打断您。
禁用irq只会禁用硬中断,就像禁用bh(softirqs)只会禁用软件中断一样,但是您需要明确指定要禁用哪个中断。有4个级别:NMI, IRQ, softtirq, process。NMI(不可屏蔽中断)可以中断IRQ、软中断、进程;IRQ可以中断一个软请求和进程;软件可以中断进程。
在local_irq_save()之后调用local_bh_disable()可能是多余的(不确定),但是如果你想禁用BH,在preempt_disable()之后调用local_bh_disable()是绝对需要的。