我最近正在阅读 Linux内核开发,我有一些与禁用抢占相关的问题。
在第7章的“中断控制”部分中,它说:
此外,禁用中断还会禁用内核抢占。
我还从书中读到,在以下情况下可能会发生内核抢占:
当中断处理程序退出时,返回内核空间之前 当内核代码再次成为可抢占时 如果内核中的任务明确调用schedule()
如果内核中的任务阻塞(导致调用schedule())
但是我无法将禁用中断与这些情况联系起来。
据我所知,自旋锁将使用 preempt_disable()函数禁用抢占。
帖子What exactly are "spin-locks"? 表示:
在单核心机器上,自旋锁只是一个“禁用中断”或“引发IRQL”,它会完全阻止线程调度。
preempt_disable()是否会通过禁用中断来禁用抢占?
答案 0 :(得分:9)
我不是调度大师,但我想解释一下我是如何看待它的。 这里有几件事。
thread_info->preempt_count
变量。你可以看到什么是preempt_disable()。试试这个: 1.获得一个旋锁。 2.通话时间表()
在dmesg中你会看到类似“BUG:schedule while atomic”的内容。当调度程序在原子(非抢先)上下文中检测到您的进程但是它自己调度时,就会发生这种情况。
祝你好运。答案 1 :(得分:2)
在我编写的监视/配置任务的测试内核模块中,我尝试通过以下方式禁用中断:
1 - 使用local_irq_save()
2 - 使用spin_lock_irqsave()
3 - 对/ proc / interrupts中的所有IRQ手动disable_irq()
在所有3个案例中,我仍然可以使用hrtimer来测量时间,即使IRQ被禁用(我正在监视的任务也被抢占)。
我觉得这个怪人很奇怪......我个人期待Sebastian Mountaniol指出的 - >没有中断 - 没有时钟。没有时钟 - 没有计时器......
Linux内核2.6.32在单核,单CPU上......任何人都可以有更好的解释吗?
答案 2 :(得分:0)
preempt_disable()
不会禁用中断。但是,它会增加抢占计数器的计数。假设您在代码路径中调用preempt_disable()
n次,则抢占将仅在第n个preempt_enable()
处启用。scheduler_tick()
(不调用中断处理程序)。但是,如果程序触发了调度功能,则如果未调用preempt_disable()
,则会发生抢占。raw_spin_lock()
不会禁用可能导致死锁的本地中断。例如,如果调用了一个中断处理程序试图锁定已经持有的自旋锁,则除非进程本身释放了它,否则将无法执行该操作,因为不会发生中断返回。
因此,最好使用raw_spin_lock_irq()
来禁用中断。答案 3 :(得分:0)
禁用中断会禁用某些形式的内核抢占,但是还有其他方式可以发生内核抢占。因此,禁用中断不是防止内核抢占的安全方法。
例如,在禁用中断的情况下,cond_resched()仍会导致抢占,但如果显式禁用了抢占则不会。
这就是为什么关于第二个问题,自旋锁不使用中断禁用来禁用抢占的原因。他们显式调用preempt_disable(),从而增加preempt_count的数量,并禁用除对schedule()的显式调用以外的所有可能发生的抢占方式。