11

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

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

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

自旋锁就其本质而言,旨在用于多处理器系统,尽管就并发性而言,运行抢占式内核的单处理器工作站的行为类似于 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,而不必单独担心。

但是源代码上没有内核版本或日期。谁能确认它是否仍然适用于最新的 Linux 内核?

4

1 回答 1

7

a) 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必须禁用中断。

于 2013-05-27T04:57:45.130 回答