了解最新(3.0.0及以上)Linux内核中CONFIG_SMP、自旋锁和CONFIG_PREEMPT之间的关系

11
为了给您提供完整的背景信息,我的讨论始于一个观察:我在ARM cortex A8 SoC上运行SMP Linux(3.0.1-rt11),这是单处理器。我很想知道禁用SMP支持是否会有任何性能优势。如果有的话,它将对我的驱动程序和中断处理程序产生什么影响。
我阅读了一些相关主题:自旋锁和内核抢占。我做了更多的谷歌搜索和阅读,但这次得到的都是过时和矛盾的答案。所以我想试试stackoverflow。
我的疑问/问题是:
a) Linux kernel默认情况下在内核空间中是可抢占的吗?如果是,这种抢占是否仅限于进程,还是中断处理程序也可以被抢占?
b) Linux内核(在ARM上)是否支持嵌套中断?如果是,每个中断处理程序(top half)是否有自己的堆栈,还是它们共享相同的4k/8k内核模式堆栈?
c) 如果我禁用SMP(CONFIG_SMP)和抢占(CONFIG_PREEMPT),那么我的驱动程序和中断处理程序中的自旋锁是否有意义?
d) 内核如何处理在执行top-half时引发的中断,即它们是否被禁用或掩码?
经过一些谷歌搜索,我发现:
对于没有编译CONFIG_SMP且没有编译CONFIG_PREEMPT的内核,自旋锁根本不存在。这是一个非常好的设计决策:当没有其他人同时运行时,没有理由使用锁。
如果内核没有编译CONFIG_SMP,但设置了CONFIG_PREEMPT,则自旋锁只是禁用了抢占,这足以防止任何竞争。对于大多数目的,我们可以认为抢占相当于SMP,不必单独担心它。
但是在中没有内核版本或日期。有人能确认它是否仍然适用于最新的Linux内核吗?

那是四个问题,所以将其分开,因为它们可能不能一起回答。 - Steve-o
1个回答

7
a) Linux的抢占式取决于是否使用CONFIG_PREEMPT进行配置,没有默认设置。如果运行make config,则需要进行选择。
b) 在Linux中,中断可以嵌套;在处理中断时,其他中断可能会触发。这适用于ARM和许多其他架构。它们全部在同一个栈上。当然,用户空间堆栈不用于中断!
c) 如果禁用SMP和抢占,则代码中的自旋锁将减少为无操作(no-op),如果是常规自旋锁,则IRQ自旋锁(spin_lock_irqsave/spin_lock_irqrestore)将变成中断禁用/启用。因此,后者仍然是必需的;它们防止任务运行您的代码和中断运行您的代码之间的竞争。
d) “顶半部分”传统上指的是中断服务程序(interrupt service routines)。驱动程序的顶半部分代码由中断运行。底半部分由任务调用(读取或写入数据等)。中断处理的详情因架构而异。
在引文中提到的内容仅适用于常规自旋锁(spin_lock函数/宏),而不适用于IRQ自旋锁(spin_lock_irqsave)。在单处理器上的可抢占内核中,spin_lock仅需要禁用抢占即可,在spin_unlock之前可以阻止所有其他任务进入内核。但是,spin_lock_irqsave必须禁用中断。
引文作者最近与某个MIPS架构的Linux中断密切合作。在该特定板上,有128个可屏蔽中断线,通过两个64位字单元进行掩码处理。内核在此基础上实现了优先级方案,因此在执行给定中断的处理程序之前,通过更新这些2x64位寄存器对较低的中断进行了掩码处理。作者加入了一种修改方式,使得中断优先级可以任意设置,而不是按硬件位置,动态地通过写入/proc条目中的值。此外,作者还加入了一个技巧,其中一部分数字IRQ优先级与任务的实时优先级重叠。因此,分配给某个优先级范围的实时任务(即用户空间线程)能够在运行时隐式地抑制一定范围内的中断。这非常有用,可以防止表现不良的中断干扰重要任务(例如IDE驱动程序代码中用于紧凑型闪存的中断服务例程,由于设计不当的硬件接口而执行繁忙循环,导致闪存写入成为系统中事实上的最高优先级活动)。因此,如果您控制客户使用的内核,则IRQ屏蔽行为不是固定的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接