設(shè)置
  • 日夜間
    隨系統(tǒng)
    淺色
    深色
  • 主題色

Linux 之父終于被勸動:用了 30 年的 Linux 內(nèi)核 C 語言將升級至 C11

量子位 2022/2/25 14:00:46 責(zé)編:長河

還在使用 89 年版 C 語言的 Linux 內(nèi)核,現(xiàn)在終于要做出改變了。今天,Linux 開源社區(qū)宣布,未來會把內(nèi)核 C 語言版本升級到 C11預(yù)計 5.18 版之后生效,也就是今年 5 月。

Linux

這個決定很突然,從發(fā)起問題到官方聲明,不過才一個星期,要知道說服固執(zhí)的 Linux 之父 Linus Torvalds 可不是件容易的事。事情的原因,說起來還有那么一點偶然的因素。

一個 bug 的連鎖反應(yīng)

問題的起源是來自上周的一次 Linux 社區(qū)討論。

一位名叫 Jakob Koschel 的博士生,在研究阻止與內(nèi)核鏈表 primitive 相關(guān)的預(yù)測執(zhí)行漏洞時,發(fā)現(xiàn)了這樣一個問題。

Linux 內(nèi)核廣泛使用由 struct list_head 定義的雙向鏈表

struct list_head {
    struct list_head *next, *prev;
    };

這種結(jié)構(gòu)通常嵌入到其他結(jié)構(gòu)中。通過這種方式,可以使用任何相關(guān)的結(jié)構(gòu)類型制作鏈表。

除此之外,內(nèi)核還提供大量可用于遍歷和操作鏈表的函數(shù)和宏。list_for_each_entry () 就是其中之一,這是偽裝成一種控制結(jié)構(gòu)的宏。問題就出在這個宏上。假設(shè)內(nèi)核包含如下結(jié)構(gòu):

struct foo {
        int fooness;
    struct list_head list;
    };

list 中的元素可用于創(chuàng)建 foo 結(jié)構(gòu)的雙向鏈表。假設(shè)有一個叫做 foo_list 的結(jié)構(gòu)聲明作為此類鏈表的頭,使用以下代碼可以遍歷此鏈表:

struct foo *iterator;

    list_for_each_entry(iterator, &foo_list, list) {
        do_something_with(iterator);
    }
    /* Should not use iterator here */

list 參數(shù)告訴宏在 foo 結(jié)構(gòu)中 list_head 結(jié)構(gòu)的名稱。這個循環(huán)將為列表中的每個元素執(zhí)行一次,迭代器指向該元素。由此導(dǎo)致了 USB 子系統(tǒng)中的一個 bug:傳遞給該宏的迭代器在退出宏后還能被使用。

這是一件危險的事情,所以 Koschel 提交了一個修復(fù)補丁,在循環(huán)后停止使用迭代器搞定了 bug。

說服 Linus

但是 Linus Torvalds 本人并不太喜歡這個補丁,也沒有看到它與預(yù)測執(zhí)行漏洞的關(guān)系。在 Koschel 詳細(xì)解釋后,Linus 承認(rèn)這只是一個普通的 bug。

然而事情并沒有那么簡單,Linus 不久后意識到了真正的根源:傳遞給鏈表遍歷宏的迭代器,必須在循環(huán)本身之外的范圍內(nèi)聲明。這種非預(yù)測性 bug 發(fā)生的原因是,C89 中沒有“在循環(huán)中聲明變量”。

像 list_for_each_entry () 這樣的宏,從根本上總是將最后一個 HEAD 入口泄漏到循環(huán)之外,僅僅是因為我們不能在循環(huán)本身中聲明迭代器變量。

如果可以編寫一個可以聲明自己的迭代器列表遍歷宏,那么迭代器在循環(huán)之外將不可見,并且不會出現(xiàn)此類問題。但是,由于內(nèi)核停留在 C89 標(biāo)準(zhǔn)上,因此無法在循環(huán)中聲明變量。

Linus 決定,那咱們還是升級吧,也許是時候轉(zhuǎn)向 C99 標(biāo)準(zhǔn)了。雖然它也有 20 多年的歷史,但至少比 C89 新,可以在循環(huán)中聲明變量。

既然 C89 如此陳舊,這么多年還沒做出改變呢?Linus 說,那是因為我們在一些古老的 gcc 編譯器版本中遇到了一些奇怪的問題,不能隨便升級。

但是,現(xiàn)在 Linux 內(nèi)核已將 gcc 的最低要求提升至 5.1 版,因此過去那些奇怪的 bug 應(yīng)該不會有了。

而另一位核心開發(fā)者 Arnd Bergmann 認(rèn)為,咱們完全可以升級到 C11 甚至更高版本。但如果升級到 C17 或 C2x,會破壞對 gcc-5/6/7 的支持,因此升級到 C11 更容易實現(xiàn)。

最終,Torvalds 贊成這個想法:“好的,請?zhí)嵝盐遥屛覀冊?5.18 合并窗口的早期嘗試一下。”接下來遷移到 C11 可能會導(dǎo)致一些意想不到的 bug,但如果一切順利,下一個 Linux 內(nèi)核版本將正式轉(zhuǎn)向 C11。

參考鏈接:

[1]https://lwn.net/SubscriberLink/885941/01fdc39df2ecc25f/

[2]https://news.ycombinator.com/item?id=30459634

廣告聲明:文內(nèi)含有的對外跳轉(zhuǎn)鏈接(包括不限于超鏈接、二維碼、口令等形式),用于傳遞更多信息,節(jié)省甄選時間,結(jié)果僅供參考,IT之家所有文章均包含本聲明。

相關(guān)文章

關(guān)鍵詞:內(nèi)核,linux

軟媒旗下網(wǎng)站: IT之家 最會買 - 返利返現(xiàn)優(yōu)惠券 iPhone之家 Win7之家 Win10之家 Win11之家

軟媒旗下軟件: 軟媒手機(jī)APP應(yīng)用 魔方 最會買 要知