关注了就能看到更多这么棒的文章哦~
VSTATUS, with or without SIGINFO
By Jonathan Corbet
January 6, 2022
DeepL assisted translation
https://lwn.net/Articles/880498/
Unix 的 signal 接口很复杂,很难用对。一些开发者评论说 signal 当前的设计是 "不可修复的(unfixable)"。因此,当 Walt Drummond 提议说要增加 Linux 系统可以管理的 signal 的数量时,全网都感到震惊。这个改动提议似乎不太可能真的落实,但其背后的目标,也就是支持其他操作系统中一个几十年前就有的功能,则很可能会得以实现。
内核能够支持多达 64 种的信号类型(signal type),这个数字似乎很合理,但是至少在某些架构上已经把所有的 64 种信号都用完了。因此在 Linux 中无法再添加新的信号类型了。Drummond 希望能把这个限制提高到 1024,从而来解决这个问题,这样肯定是足够了。提高这个限制的话也需要对用户空间 API 做一些小改动(例如,在传递给 realtime signal handler 函数的信息中放入的 signal mask 也需要相应地增大了),这有可能会导致应用程序运行出错,因此这就意味着需要进行额外 review。但是,如果想要支持更多的 signal,这个做法似乎是必需的。
开发人员们马上就问为什么需要增加 signal,并要求 Drummond 尽可能地找一个替代方案。正如 Eric Biederman 所说:
只要能有任何其他替代方案,那就不要扩大系统支持的 signal 数量。signal 必须要支持现存的接口,才是有意义的。对于新的应用来说,通常总是有更好的解决方案。
那么,为什么必须要新增 signal 呢?答案来自于它比 Linux 诞生更加久远的历史。TOPS-10 操作系统是由 DEC 公司在 20 世纪 70 年代所开发的,它提供的一个功能就是当用户输入 control-T 时会打印一行状态信息(当前在运行的是什么,消耗了多少 CPU 时间等)。这是一个能让用户确定系统是否仍然正常运行、并在继续推进当前运行的 task 的快速验证方法。这个功能后来在 VMS 中得到了应用,今天它仍然存在于一些 BSD 变种中。然而 Linux 并没有采用这种这个功能,至少没有一个相同形式的功能。
在内核中要支持这个被称为 VSTATUS 的功能,有两个方面的工作要做。首先是在终端驱动(terminal driver)中识别出这个 control 控制字符输入,这个工作是跟识别其他控制字符(比如检测给运行中的进程发送 SIGINT signal 的 control-C)实现逻辑相同。然后,内核会采用两种方式来响应这个按键:
内核将直接向 terminal 终端打印一行状态信息,其中包含关于当前运行进程以及系统状态的通用信息。
会给当前在 terminal 终端上运行的进程发送一个 SIGINFO 信号。应用程序可以捕获这个信号来触发打印他们自己的一些状态信息。比如,一个进行 copy 的程序就可以告诉用户这个 copy 工作的当前进展。
Linux 内核并没有实现 VSTATUS,所以上面两方面的工作它都不会去做。在 terminal 驱动程序中添加打印状态信息的能力并不难,在发生某个 event 的时候去发送 signal 也不困难。问题是,Linux 没有实现 SIGINFO,所以需要添加这个信号,而如上所述,已经没有空间给新的 signal 了。因此才引出了 Drummond 的 patch set。
这不是第一次提出要支持 VSTATUS,此前在 2014 年就已经提过了,2019 年又出现过,肯定还有其他一些时候也有提过。在 2019 年,Arseny Maslennikov 试图通过将 SIGINFO 定义为 SIGPWR 的同义词(synonym)来绕过 signal 数量限制。SIGPWR 信号可以根据发起的时机来分别表示即将发生供电故障(power failure),还是电源已经恢复了。无论怎样,这个信号只会传递给 init 进程。而且在当前系统中,往往很少使用这个信号。将其重复利用到 VSTATUS 的话,只需要将 SIGPWR 的默认 action 改为 "ignore",其他方面应该不会对用户空间有什么影响。
或者说,开发者原本希望是这个样子。其实 SIGPWR 尽管在现实世界中很少使用,但确实有用到。正如 Ted Ts'o 所指出的,systemd 就可能会对其做出相应的处理。改变 SIGPWR 的默认处理方式虽然确实有可能不会破坏任何用户空间行为,但很难完全确认这一点。如果真的有什么问题的话,可能会在几年后当这个改动进入企业内核(enterprise kernel)时才会出现。那时,这个问题就会陷入两难境地,几乎无法能给出一个让所有人都满意的 fix 了。所以,内核开发者们当然也就不愿意做出这样的改动了。
多年来,人们一直在质疑这个功能是否真的有需要。正如 Greg Kroah-Hartman 在 2019 年指出的那样,内核的 "magic SysRq" 功能就完成了 VSTATUS 所实现的全部功能(甚至还大大超出了)。但是 magic SysRq 只在系统控制台(system console)下是可用的。正如 Biederman 在上述讨论中指出的,那些通过 SSH 来操作系统的场景就是一个非常有说服力的困难了。因此,VSTATUS 确实又是有需要的。
既然如此,下一步该怎么做呢?Ts'o 在上面的讨论中提出了一个建议,那就是实现 VSTATUS,并在内核中打印状态行,但是不用向用户空间发送 SIGINFO 信号。这样就不需要再增加一个新的信号或重复利用某个原有信号了,从而能避免所有这些困难。这种实现方式会导致用户空间无法据此添加汇报应用特有的状态信息的能力,但此前已经实现过 SIGINFO 的处理函数的应用软件非常少。Drummond 说只有 sleep、dd 和 ping 之中有这样的功能,"所以整体来说并不会导致工具中损失一个巨大的功能,也不会有非常多的历史遗留软件必须要等 SIGINFO 来用"。因此他欣然同意可以省去 SIGINFO 这部分功能。
截至目前,关于 SIGINFO 的后续 patch set 还没有被发布出来。等到发布出来之后,应该不会有多少人会反对合入 mainline。到那时,Linux 就会拥有 BSD 已经提供了 VSTATUS 中的主要功能。如果今后发现有人真的需要 SIGINFO 这部分功能,那么到时候可以重新考虑这个问题。而在此时,内核社区还是希望把这个问题先踢到一边免得惹上麻烦。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~