Sat*_*mar 8 smp linux-device-driver linux-kernel preemption spinlock
为了给你完整的上下文,我的讨论开始于观察我在基于ARM皮层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内核?
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必须禁用中断.