乐趣区

关于linux:终于30-岁的-Linux-内核-C-语言将升级到-C11

上周,Linux 内核邮件列表上对于“社区最近探讨了是否为内核采纳古代 C 语言规范”的信息引发业内关注。刚刚,Linux 开源社区已正式发表:内核 C 语言版本将在将来降级到 C11,且预计将在往年 5 月份的 5.18 版本之后失效。

这个忽然的决定,也终于让领有 30 年历史的 Linux 内核 C 语言迎来了降级。

家喻户晓,想要压服执著的 Linux 之父 Linus Torvalds 绝非易事。那么,这一次 Linus Torvalds 为何终于松口了呢?这外面,仿佛还真有那么一点偶尔因素。

事件起因还是要回到上周的那次的 Linux 社区探讨。

一条 Bug 引发的“连锁反应”

据悉,过后一位名叫 Jakob Koschel 的博士生正在钻研与内核链表原语相干的揣测性执行破绽,过程中他发现了一个问题:Linux 内核宽泛应用 struct list_head 定义的双链表:

struct list_head {

struct list_head *next, *prev;

};

通常,开发者通过将此类构造嵌入其余构造里的形式,来使任何相干的构造类型都能够创立链表。同时,该内核还提供了大量可用于遍历和操作链表的函数和宏。其中一个就是 list_for_each_entry(),这是一个伪装成控件构造的宏。

凑巧,问题出在了这个宏上。

咱们假如该内核蕴含以下构造:

struct foo {

int fooness;
struct list_head list;

};

List 中的元素则可用于创立 foo 构造的双链接列表。

假如有一个名为 foo_list 的构造申明作为此类链表的头,则能够应用以下代码遍历此链表:

struct foo *iterator;

list_for_each_entry(iterator, &foo_list, list) {

do_something_with(iterator);

}
/ Should not use iterator here /

list 参数通知宏 foo 构造中 list_head 构造的名称。对于迭代器指向的列表中的每个元素,该循环将执行一次。

而这样就会导致 USB 子系统中呈现谬误:在退出宏后,传递给该宏的迭代器仍可应用。当然,这是一件十分“危险”的事件。

所以,Koschel 提交了一个补丁,从新编写了有问题的代码,通过在循环完结后停止使用迭代器来修复这个谬误。随后,Jakob Koschel 将(投机性平安列表迭代器倡议)修复的与内核链接表相干的预测执行破绽的补丁提交给了 Linus Torvalds。

Linux 之父终于被压服

最后,Linus Torvalds 自己仿佛对这个补丁并不是很喜爱,也不晓得该补丁与揣测性执行破绽有什么关系。但通过 Koschel 具体解释之后,Linus 抵赖了这只是一个常见的 Bug。

然而,事件并非那么简略,Linus 很快就意识到了真正的问题:传递给链表遍历宏的迭代器必须在循环自身之外的范畴内申明。

而呈现这种不可预测的谬误的起因是 C89 中没有“在循环中申明变量”。

咱们晓得,尽管 Linux 内核正在疾速倒退,但它也依赖于一些十分古老的工具,其中之一就是其内核代码仍在应用 1989 年版的 C 语言规范,也就是说,该规范是在内核我的项目启动 30 多年前编写的。

像 list_for_each_entry()这样的宏,基本上总是将最初一个 HEAD 条目透露出循环,就是因为不能在循环自身中申明迭代器变量。

如果能够编写一个迭代器列表遍历宏来申明本人,那么迭代器在循环外就不可见,也不会呈现这样的问题。

然而,因为内核停留在 C89 规范上,因而不可能在循环中申明变量。

因而,Linus 决定,“让咱们降级一下”,兴许是时候降级到 C99 规范了,只管 C99 也有 20 多年的历史了,但它至多比 C89 更新一点,且能够在循环中申明变量。

既然 C89 曾经过期了,为什么这么多年都没有扭转呢?Linus 解释称,“这是因为咱们在一些旧的 gcc 编译器版本上遇到了一些奇怪的问题,这些版本不能随便降级。”

然而,当初 Linux 内核曾经将 gcc 的最低要求进步到了 5.1 版,过来那些奇怪的 Bug 应该隐没了。

另一位外围开发者 Arnd Bergmann 也对此事比拟关注,他认为能够降级到 C11 甚至更高版本,但降级到 C17 或 C2x 会毁坏 gcc-5/6/7 反对,因而降级到 C11 更容易实现。

最终,Linus Torvalds 反对了这个想法,并发表将“在 5.18 版合并窗口的晚期尝试一下”。

尽管接下来转移到 C11 可能会导致一些意想不到的 Bug 也说不定,但如果一切顺利,下一个 Linux 内核版本将正式转移到 C11。您对此次降级事件有何认识呢?也欢送在下方交换互动。

退出移动版