关注了就能看到更多这么棒的文章哦~
The imminent stable-version apocalypse
By Jonathan Corbet
February 5, 2021
DeepL assisted translation
https://lwn.net/Articles/845120/
人们经常说,stable-kernel release 应该要是稳定的(stable),也就是说,,stable kernel 比起 mainline 版本来说,更不容易出现 ABI 被破坏的情况,当然最好是绝对不要出现。不过对于未来的 stable kernel 来说,可能很难给出这个承诺,原因很简单:没有人预料到某些内核版本会有超过 255 个小更新版(minor update)。
在 Linux kernel 的历史上,很少有开发者会维护某个内核版本好几年,并且维护过程中发布的更新版本(maintenance release)也较少。也有一些例外,2.4 版本是 2001 年初发布的,Willy Tarreau 在 11 年多以后终于停止了对其进行的维护工作。即便如此,最终的版本也仅仅是 2.4.37,不过在后来补发的 11 个微小 "fixup" release 之后,人们也可以称之为 2.4.48。很少有哪个内核版本会得到长期维护,,而且间隔也会很长。
不过近年来,这种情况已经发生了变化,一些旧内核版本得到了更多的长期维护。因此,在 2 月 3 日的时候发布了 4.9.255 和 4.4.255 更新版。这两个 kernel 版本中此前合入了 18,765 个和 16,986 个 patch,而且目前合入速度仍然没有放缓。目前公布的计划是会维护 4.9 直到 2023 年 1 月,而 4.4 会维护到 2022 年 2 月。
正如 Jari Ruusu 所指出的,kernel-release 名字中的数字现在会导致一些麻烦。内核中定义了一些与版本号有关的宏,这些宏位于 include/generated/uapi/linux/version.h 。
#define LINUX_VERSION_CODE 330496
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
第一个宏 LINUX_VERSION_CODE,是在最顶层的(top-level) makefile 中计算出来的,它来自于:
(5 << 16) + (11 << 8) + 0
0x50b00 这个数字表明这是一个 5.11-rc 的内核,这和 KERNEL_VERSION(5,11,0)的结果一致。
很容易看出来,一旦 minor version(KERNEL_VERSION()宏中的 "c")超过 255,这两个宏都会失效。在 4.9.255 内核上这个宏会生成 0x409ff,但在 4.9.256 上,它反而会返回 0x40a00–看起来像 4.10.0。这样肯定会在用户社区中造成混乱。
这个问题对于稳定内核的维护者来说已经有所准备了,Sasha Levin 在 1 月中旬发布了一个 patch set 试图解决这个问题。其将 LINUX_VERSION_CODE 和 KERNEL_VERSION()中的 minor version 都改为 16 bit,从而避免溢出。这个补丁进入了 linux-next,但似乎不太可能被接受,正如 Jiri Slaby 所指出的,这些宏在 user space 有使用到,成为了内核 ABI 的一部分。他补充说,GNU C 库和 GCC 编译器(特别是 BPF 代码)中的逻辑都是跟目前内核版本中的代码相吻合的,如果我们光改动内核的话是不够的。内核中还有很多其他地方与用户空间交互时都会依赖这些版本号相关的代码,media ioctl()命令就是个例子。改变内核中 KERNEL_VERSION() 的工作方式的话,这会破坏那些使用旧的宏来编译的程序,这是不允许的。
那么该怎么做呢?在写这篇文章的时候,这个问题还没有解决,但有几个方案摆在桌面上。
-
Ruusu 指出了这个问题,建议稳定版可以开始递增 EXTRAVERSION 字段;这个字段通常包含 -rc7(用于 mainline 的 test release)或 Git 提交 ID 等字符串。minor version 保持在 255。这样可以避免破坏 ABI,但也会让用户空间的代码很难区分 255 之后的 stable release。这也可能会给那些使用该字段来标识自己的 build 版本的发行版提供商带来一些小麻烦。
-
stable kernel 维护者 Greg Kroah-Hartman 觉得他可以 "先不要管它,看看会发生什么"。但是,正如 Slaby 指出的那样,这将造成上述的溢出问题,会让 user space 感到混淆。他说,如果要让它移除的话,还是必须要将 minor version 保持在 8 位,这样就回到 0,这是否会造成混乱是另一个问题了。通常来说人们总是期望版本号是永远单调增加的。
不过最可能的结果可以还是从内核历史中学习。很久以前,mainline 内核版本有三个数字,而不是两个。以前版本号是 2.6.30 这样的。在那个时候,minor version 字段不能用于 stable 版本更新,所以使用了 EXTRAVERSION 字段代替。在 2.6.30.3 的 makefile 中,我们可以看到。
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 30
EXTRAVERSION = .3
NAME = Man-Eating Seals of Antiquity
这个解决方案此前多年一直可以正常工作,所以现在应该也还是有办法再用起来的。很可能是让 SUBLEVEL 一直停留在 255,而 EXTRAVERSION 则表示真正的 release number。
Leon Trotsky 曾经说过 "所有可能发生在一个人身上的事情中最令人意想不到的,就是 old age"。也许这里也有类似的力量在起作用。对内核开发者来说最意想不到的事情就是耗尽了 bit 位数。这个版本号溢出问题本来可以提前就预见到,并且可以预测到会发生的日期。但现在必须在下一个稳定内核发布之前找到某种解决方案。可喜的是,这个问题应该比 old age 问题要更容易解决。
更新:Kroah-Hartman 似乎选择了 "什么都不做" 的方案,发布了 4.9.256 和 4.4.256,这两个版本都对版本号加一,但没有做其他任何实际改动。"我会尽量暂缓一周,之后再做一个'真正的'4.9.y 版本,这样可以给大家一段时间进行测试并给我回复。4.9.y 版本中排队等着进的 patch 非常多,所以我不愿意等太长时间,这个作为给大家的提醒……"
更新 2:最后,似乎会采取固定版本号的解决方案,minor number 今后固定为 255。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~