但请记住,“禁用 irqs” 是一种根本上不安全的禁用抢占的方式 - 任何将抢占计数减少到 0 的 spin_unlock() 都可能会触发重新调度。一个简单的 printk() 可能会触发重新安排。
如果 IRQ 被禁用,那么该 CPU 内核上的定时器中断也应该被禁用。自然,它应该依次禁用调度程序(抢占)。为什么调用 irqsdisabled() 来禁用抢占是不安全的方法?
此外, printk() 如何触发重新安排?
答案1
是的,如果 IRQ 被禁用,定时器中断将被禁用并且任务调度不再发生。不安全的部分是“如果”:如果您依赖于禁用的 IRQ,您需要绝对确保在禁用 IRQ 的情况下运行的所有代码都遵守这一点。这在内核中可能相当困难,因为自旋锁自行禁用和启用抢占(在某些情况下与 IRQ 一起),许多代码都使用锁,包括printk
(以确保日志消息不会混淆)。每当锁被释放时,即使 IRQ 被禁用,您也会面临重新安排的风险(以运行等待锁的代码):preempt_enable()
显式调用__preempt_schedule()
当其计数器达到零时,因此不需要定时器中断。
因此,使用适当的抢占支持功能会更安全,特别是在面向未来方面:您可能很清楚您现在正在编写的代码中的约束,但其他人不会更改它(并且“某人否则”包括“六个月后的你”)。
答案2
因为定时器中断(或一般中断)并不是内核抢占的唯一原因。有些函数仍然可以触发抢占(例如 cond_resched()),这些函数期望显式禁用抢占。