LWN:平衡好处理软中断以及实时任务!

本文讨论了内核中的软件中断如何影响实时任务,特别是安卓系统中的音频卡顿问题。作者提出了两个改动:一是调度器在安排实时任务时避免选择处理慢速软件中断的CPU;二是优先考虑实时任务,将慢速软件中断推迟到ksoftirqd处理。这些改动已经在安卓内核上使用多年,改善了实时测试的延迟结果。然而,仍存在改进空间,如直接阻止软件中断处理以优先服务高优先级任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

Juggling software interrupts and realtime tasks

By Jonathan Corbet
December 2, 2022
DeepL assisted translation
https://lwn.net/Articles/915320/

软件中断(software-interrupt)机制是内核中最古老的子系统之一了。甚至可以说,这部分代码背后的基础设计都早于 Linux 本身。软件中断会打断其他工作,因此,几乎是从它们出现的那一天开始,开发者就已经很希望看到它们能早点消失了。不过人们一直还没能达到这个目的,而且看起来也不会很快达到。相反,安卓系统长期以来一直带有一个 patch 从而试图将软件中断的影响降到最低,至少在某些情况下是这样。John Stultz 现在正在发布这部分代码,其中包含了多位作者的贡献,并希望能将其纳入 mainline 内核。

硬件中断(通常简称 "中断")是在系统中某个物理硬件组成部分希望能得到内核的关注时所发出的;它们通常会立即触发一个 trap 进入特殊的处理函数(handler function)。由于中断会让系统从它当前正在做的工作中跳出来,因此中断处理程序必须迅速完成它们的工作;也就没有时间进行什么扩展处理(extended processing)。这并不是一个什么新问题;Linux 之前的 Unix 系统就经常包括一个 "bottom half(下半部)" 的概念,用左一种推迟把中断处理程序(interrupt handler)中无法完成的工作推迟处理的一种方式。

Linux 内核里也不得不开发了一些机制,用来将中断处理工作推迟到更合适的时机。这些机制之一就是软件中断(或 "软中断,softirq")。它在 0.99 版本的内核中刚出现的时候采用了大家熟悉的 "bottom half "的名字;"softirq "这个词是直到 1.1.77 版本的开发版本中才出现的。缩写 "bh"("bottom half")仍然存在于跟软件中断有关的内核函数名称中。

在目前的实现里把若干个软件中断 "向量" (software-interrupt "vector")分配给了相应的子系统。每当这些子系统中某一个不得不推迟一些工作时,它就会在一个 per-CPU mask 中设置一个 bit,从而在后续某个时刻来调用其软件中断处理程序(software-interrupt handler)。通常,软件中断会在硬件中断处理完成后立即运行,也就是说它是以高优先级运行的,优先级高于内核的其他工作。软件中断机制是保留给内核中少数核心子系统使用的,比如网络子系统和块设备子系统,但有一个很大的例外:内核的 tasklet 机制是对任何子系统都可用的,它会用来在软件中断处理中执行 tasklet。

软件中断在一个运作良好的系统中也会产生延迟,所以它们长期以来一直吸引着那些对响应时间感兴趣的开发者的注意力。在配置为实时抢占(realtime preemption)的内核中,软件中断就像其他进程一样是在一个进程中被处理的,因此它们的优先级可以根据其重要性来进行设置。不过,我们大多数人运行的都不是这种实时抢占内核,所以软件中断处理通常会从其他那些希望运行的任务中抢一些时间。即使在正常的系统中,一个产生大量软件中断的系统最终也会将它们推迟到 per-CPU ksoftirqd 内核线程中。

通常情况下,人们总是希望 realtime task 总是系统上最优先的工作,哪怕是没有运行 realtime kernel 的系统也是一样。但是,软件中断的处理工作的优先级超过了 realtime task,并且会阻止它们在最后期限前完成任务。已经确实看到过软件中断引入的延迟在安卓系统上引起了 audio glitch(音频卡顿问题),从而引出了 Stultz 现在所提出的工作。

这个提议包含了两部分的改动,第一个部分是对 scheduler 针对 realtime task 的安排进行了修改。目前,当一个 realtime task 可以运行时,scheduler 将搜索一个看起来有足够计算空间 CPU 来运行该任务;这个检查的目的之一就是防止将一个资源密集型的任务放在一个缓慢的 CPU 上。Stultz 的 patch 增加了一个新的检查,就是看一下候选 CPU 是否正在处理(或即将处理)一个 "slow" 的软件中断,也就是预计需要相当多的处理时间的软件中断;为了能做出这个决策,他把来自网络子系统或者块设备子系统的软件中断定义为 "slow" 的软件中断。如果 CPU 确实在忙着做这些事,那么 scheduler 就会尝试把 realtime 放在其他 CPU 上,这样,希望该任务能更快地获得对 CPU 的访问。

第二个改动,改变了内核选择运行软件中断处理程序(software-interrupt handler)的方式。通常,这些处理程序会尽快在当前的 CPU 上运行,除非 ksoftirqd 线程已经在运行状态了(running)。在这种情况下,它们会被排在 ksoftirqd 那里处理。这组 patch 会让内核在运行软件中断处理程序之前,先检查当前 CPU 上是否有一个 realtime task 在运行;如果有的话,并且软件中断是 "slow" 类型的,那么就会被推迟到 ksoftirqd 上去,从而使得 realtime task 可以继续运行。更快的软件中断(比如那些 timer 中断)仍然会在当前 CPU 上立即执行。

为了实现这种分割处理,就需要一个很微妙的改动。在目前的内核中,如果 ksoftirqd 在 CPU 上运行,所有的软件中断都会被推迟到由它来处理。如果这些改变是生效状态(有新增一个 kernel configuration option 来配置),"fast" 软件中断将会被立即处理,无论 ksoftirqd 是否正在运行。这个改动是必要的,因为这组 patch 新增的对较慢的软件中断处理程序的延迟动作,可能会导致 ksoftirqd 在系统整体的软件中断工作量不大的时候运行。在之前的测试中,较快的中断处理程序可能会不应该地被延迟到 ksoftirqd。不过,现在新的代码就可能可以在软件中断已经有很多工作的时候不推迟它们的处理了。

这项工作得到最终结果是,诸如 cyclictest 这样的 realtime test 中的 latency 延迟结果要好很多。这些 patch 已经在安卓内核上使用了 "若干年",按理来说不会造成问题,至少在这种环境中不会。即便如此,Peter Zijlstra 对这项工作还是并不完全满意;他建议,最好是在有高优先级任务要运行时直接停止软件中断处理。他有一组 patch 做出了这样的改动,他以前曾发布过这些补丁,但他也承认,当时这项工作 "由于性能出现退化而没能成功"。

Stultz 对 Zijlstra 的这一系列 patch 进行了尝试,得出的结论是,虽然它改善了这种情况,但并没有完全解决这个问题。具体来说,如果某个软件中断处理程序会运行很长时间的话,这个改动没有什么帮助,而这种情况确实是实际生活中会发生的事情。因此,他说 "我不确定它真的能让我们放弃这组 softirq-rt placement optimization patch"。希望最终能制定出某种能让所有相关开发者都接受的解决方案。否则,很可能是安卓还需要继续背负这组 patch 好几年。

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

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

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

format,png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值