了解最新(3.0.0及更高版本)Linux内核中CONFIG_SMP,Spinlocks和CONFIG_PREEMPT之间的链接

时间:2013-01-17 13:43:13

标签: linux-kernel linux-device-driver spinlock smp preemption

为了给你完整的上下文,我的讨论开始于观察我在基于ARM皮层A8的SoC上运行SMP linux(3.0.1-rt11),这是一个单处理器。我很想知道通过禁用SMP支持是否会有任何性能优势。如果是,它会对我的驱动程序和中断处理程序产生什么影响。

我做了一些阅读并遇到了两个相关主题:自旋锁和内核抢占。我没有做更多的谷歌搜索和阅读,但这次我得到的是一些陈旧和矛盾的答案。所以我想让我试试stackoverflow。

我怀疑/问题的根源是Linux设备驱动程序第3版第5章中的这一段:

  

Spinlocks本质上是用于多处理器的   系统,虽然是一个运行抢占式的单处理器工作站   就并发性而言,内核的行为类似于SMP,。如果一个   非抢先式单处理器系统曾经锁定了一个锁,它   永远旋转;没有其他线程能够获得   CPU释放锁定。出于这个原因,自旋锁操作就可以了   启用了不抢占的单处理器系统进行了优化   什么都没有,除了改变IRQ掩蔽的那些   状态。因为先发制人,即使你从不期望你的代码   在SMP系统上运行,您仍然需要实现正确的锁定。

我的疑惑/问题是:

a)默认情况下Linux内核是否在内核空间中抢先一步?如果是,此抢占是否仅限于进程或中断处理程序也可以被抢占?

b)Linux内核(在ARM上)是否支持嵌套中断?如果是,每个中断处理程序(上半部分)是否都有自己的堆栈,或者它们共享相同的4k / 8k内核模式堆栈?

c)如果我禁用SMP(Config_SMP)并且抢占(Config_preempt)将在我的驱动程序和中断处理程序中旋转锁定有意义吗?

d)内核如何处理在执行上半部分时引发的中断,即它们会被禁用还是被屏蔽?

经过一些谷歌搜索后,我发现了这个:

  

对于没有CONFIG_SMP但没有CONFIG_PREEMPT编译的内核   自旋锁完全不存在。这是一个很好的设计决定:   当没有其他人可以同时运行时,没有理由拥有   一把锁。

     

如果在没有CONFIG_SMP的情况下编译内核,但CONFIG_PREEMPT是   设置,然后自旋锁只是禁用抢占,这足够了   防止任何比赛。在大多数情况下,我们可以将先发制人视为   相当于SMP,不用担心它。

source上没有内核版本或日期。任何人都可以确认它是否仍然适用于最新的Linux内核?

1 个答案:

答案 0 :(得分:6)

a)Linux是否优先取决于是否以这种方式配置Linux 与CONFIG_PREEMPT。没有默认值。如果您运行make config,则必须选择。

b)中断在Linux上嵌套;在处理中断时,其他中断可能会中断。在ARM和许多其他架构上都是如此。它们都在同一个堆栈上。当然,用户空间堆栈不用于中断!

c)如果您禁用SMP和抢占,如果它们是常规自旋锁,则代码中的自旋锁将减少为无操作,并且IRQ自旋锁(spin_lock_irqsave / spin_lock_irqrestore)将变为中断禁用/启用。因此,后者仍然是必不可少的;它们可以阻止运行代码的任务与运行代码的中断之间的竞争。

d)“上半部分”传统上是指中断服务程序。驱动程序的上半部分代码由中断运行。下半部分由任务调用(读取或写入数据或其他)。中断处理的细节是特定于体系结构的。

  

我最近与特定MIPS架构上的Linux中断密切合作。在该特定电路板上,有128个中断线可通过两个64位字屏蔽。内核在此基础上实现了优先级方案,因此在为给定中断执行处理程序之前,通过更新这些2x64位寄存器来屏蔽较低的处理程序。我实现了一个修改,以便可以任意设置中断优先级,而不是硬件位置,并通过将值写入/proc条目来动态设置。此外,我提出了一个黑客攻击,其中数字IRQ优先级的一部分与任务的实时优先级重叠。因此,分配给特定优先级范围的RT任务(即用户空间线程)能够在运行时隐式地抑制某一范围的中断。这对于防止行为不当的中断干扰关键任务非常有用(例如,用于紧凑型闪存的IDE驱动程序代码中的中断服务程序,由于设计糟糕的硬件接口而执行繁忙循环,导致闪存写入成为系统中事实上最高优先级的活动。)无论如何,如果你控制客户使用的内核,那么IRQ屏蔽行为就不是一成不变的。

问题中引用的陈述仅适用于常规自旋锁(spin_lock函数/宏)而不是IRQ自旋锁(spin_lock_irqsave)。在单处理器上的可抢占内核中,spin_lock只需要禁用抢占,这足以在spin_unlock之前将所有其他任务保留在内核之外。但是spin_lock_irqsave必须禁用中断。