LWN:实时内核的嵌套下半部相关的锁!

关注了就能看到更多这么棒的文章哦~

Nested bottom-half locking for realtime kernels

By Jonathan Corbet
June 17, 2024
Gemini-1.5-flash translation
https://lwn.net/Articles/978189/

软件中断处理程序 (也称为 "底半部", bottom halves) 在 Linux 内核中有着悠久的历史;在很长一段时间内,开发者一直希望能够摆脱它们。它们的一个不幸特征是它们会给无关进程的执行带来意想不到的延迟;这个问题在实时抢占社区中尤为突出。在那里采用的解决方案也带来了自身的问题;为了应对这种情况,Sebastian Andrzej Siewior 正在 提出 一种针对内核构建成实时系统下使用的新的加锁机制,该机制可能也对非实时用户有利。

在正常的内核构建中,如果需要,软件中断处理程序会在内核所能找到的最早机会运行;通常情况下,这会在硬件中断处理程序完成之后或从内核返回到用户空间时立即发生。无论哪种方式,软件中断处理都会延迟进程的执行,而该进程可能与中断的产生无关。对于大多数系统而言,这种延迟通常不是问题,但实时内核最关注的是响应时间;实现不好的软件中断处理程序可能会导致一个实时任务错过其截止期限。

事实证明,实时开发者一直不相信会要在过去的二十多年里一直致力于这个项目并且出于软件中断处理程序的阻挠。因此,这些处理程序被设置为可抢占的,就像实时内核中的几乎所有其他内容一样。但是,这种更改只解决了一部分问题。内核大量使用 per CPU 变量来避免处理器之间的争用;只要没有其他 CPU 可以访问内存位置,就不会存在争用,也不需要加锁来确保互斥。当然,除非软件中断处理程序运行并尝试访问相同的数据。

为了避免此类问题,内核代码可以调用 local_bh_disable() ,这会阻止软件中断处理程序的执行,直到调用 local_bh_enable() 为止。对 local_bh_disable() 的调用也会禁用正在运行的任务的抢占和迁移,确保它在临界区期间独占访问 CPU。这解决了与同一 CPU 上的软件中断处理程序(或任何其他内核代码)竞争的问题,但为实时内核带来了另一个延迟问题;只要抢占被禁用,更高优先级的进程就无法在该 CPU 上运行,这再次威胁到那些要更高优先级进程的延迟。

实时代码树中针对 那个 问题的解决方案是,在禁用软件中断处理程序时使任务可抢占。但是,由于任务可能依赖于 local_bh_disable() 来阻止其他任务访问其 per CPU 数据,因此 local_bh_disable() 在实时内核中会对每个 CPU 进行加锁。因此,在任何一个特定时刻,只有一个任务可以在禁用软件中断的情况下在任何一个特定 CPU 上运行。

但是,几乎不言而喻,存在 另一个 问题。如果低优先级进程进入 local_bh_disable() 部分,它可能会在该部分被抢占,并被阻止执行(以及恢复软件中断)很长时间。这可能会阻止更高优先级进程完成它自己的 local_bh_disable() 调用。换句话说,这是一个典型的优先级反转情况。这里,问题因以下事实而加剧:很可能这两个任务之间没有实际的争用;它们可能正在调用 local_bh_disable() 来保护完全不同的数据。

这种情况突出了禁用软件中断处理的一个问题:它本质上是一个大的锁,它不提供任何关于它实际保护哪些数据的指示。这反过来指出了一个潜在的解决方案:用细粒度锁定替换大锁,该锁用来保护一组有限且定义明确的数据。这就是 Siewior 的补丁集采用的方法。具体来说,它添加了一对新的宏:

local_lock_nested_bh(local_lock_t /lock);
local_unlock_nested_bh(local_lock_t /lock);

使用此机制需要审核每个 local_bh_disable() 的使用位置,找出其中保护了哪些数据,并向该数据结构添加一个 local_lock_t(一种专门的锁,只阻止来自同一 CPU 的访问)。然后可以将该锁传递给 local_lock_nested_bh() ,从而做到仅在不阻止无关代码的并发执行的情况下保护该结构。

使用这种方法的代码仍然需要调用 local_bh_disable() 来阻止软件中断处理程序的访问,并防止迁移到另一个 CPU。但是,一旦所有 local_bh_disable() 部分都经过审核和调整(这项工作让人想起 消除大内核锁的漫长努力),就可以移除实时内核在 local_bh_disable() 中获取锁的动作,从而消除一个重要的争用和延迟来源。与补丁系列一起发布的基准测试结果表明,在移除该锁后,网络工作负载有了显著的改进(14.5%)。

对于非实时内核, local_lock_nested_bh() 基本上相当于不做任何操作,尽管它确实为调试目的向加锁检查器提供信息。本地锁对非实时内核没有影响,也不需要任何存储。因此,此补丁满足了从一开始就限制实时开发的一条规则:实时相关的功能不能对非实时内核的性能产生影响。

但是,这项工作将对内核的其余部分有重大益处,即使它在大多数情况下不改变生成的代码。使用当前的 local_bh_disable() 模式,没有关于正在保护哪些数据的指示。这使得难以推断并发访问,并使引入错误的可能性更大。完成这项工作后,将记录受影响数据结构的锁定规则;在许多情况下,就可能可以做到完全停止禁用软件中断,转而使用更集中的锁定方案。

此补丁集是其第六个版本。以前的发布之后进行了一些重大变化,主要是某些网络子系统如何更改以使用新机制;核心概念基本保持不变。一些开发者已经表示接受这项工作,因此很有可能它会在不久的将来被合并到上游。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

6e9f9771f2a853deb32d50ee3718d1e7.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值