Torvalds:作为 C 语言维护者,你可以避免使用 Rust,但不能干涉它。

内核之变 Linux 中的 Rust 传奇进入 "大写的 Linus "阶段

💬 173 条评论 | |

内核之变 Linux 中的 Rust 传奇进入 “大写的 Linus “阶段

Rust 是一种比 C 语言更现代、内存更安全的语言,曾一度被认为是一种稳定、平和、循序渐进的 Linux 内核语言。

2021 年,Linux 内核领导者,如创始人和领导者 Linus Torvalds 本人,对该语言印象深刻,但采取了 “观望 ”态度。2022 年 10 月,Torvalds 批准了在内核中添加支持 Rust 代码的拉取请求。

然而,到了 2024 年末,Rust 的爱好者们对他们的努力陷入僵局和受阻感到沮丧,Rust for Linux 的负责人也因为 “非技术性的废话 ”而辞职。托瓦尔兹当时表示,他理解进展缓慢的原因,但 “老一代内核开发人员已经习惯了 C 语言”,“并不太愿意学习一门新语言”。尽管如此,这仍然可以被认为是正常的开源辩论。

但在过去的两个月里,Linux 内核邮件列表中的一个版块的气氛变得紧张起来,现在可能正在走向解决–尽管 Torvalds 认为 “不需要非黑即白”。另一位长期领导者 Greg Kroah-Hartman 也基本同意这一观点: Rust 可以而且应该进入内核,但如果想继续使用 20 多年的 C 代码,就不能强迫任何人使用 Rust。

此前,on Rust of Our Lives

本月早些时候,Asahi Linux 项目负责人赫克托-马丁(Hector Martin)辞去了 Linux 维护者的职务,同时也离开了 Asahi 项目,理由是对在内核中实施 Rust 的路障感到倦怠和沮丧。马丁认为,Rust 是为苹果最新芯片组制作高效、安全驱动程序所必需的驱动程序。直接内存访问(DMA)API 的维护者克里斯托夫-赫尔维格(Christoph Hellwig)反对在他的部门中使用 Rust 代码,理由是跨语言代码库的维护工作非常痛苦。

托瓦尔兹被认为是 1991 年推出的 Linux 内核的 “终身仁慈的独裁者”,他起初批评马丁把自己的问题带到社交媒体上,对内核进程不够宽容。 “托瓦尔兹写道:”要不你接受现实吧,也许问题出在你自己身上。

但 Hellwig 随后又发表了一篇更长的短文,概述了他对 Rust 绑定(或 Rust 库的翻译,可以与 C 语言中的对应库协同工作)的反对意见,并继续他之前将这种多语言允许性与 “癌症 ”相提并论的观点。“我想知道这个 Rust “实验 ”的目标是什么: 如果我们想解决内存安全方面的现有问题,我们就需要针对现有代码进行修复,并找到改造的方法,”Hellwig 写道。他还表示,托瓦尔兹 “私下说过,他绝对会不顾维护者的反对合并 Rust 代码”。

双向 “保护墙

托瓦尔兹周四的回应确实对内核中的 Rust 绑定做了一些澄清,但同时也澄清了顽固的 C 语言程序员能够和不能控制的东西。

像 Hellwig 这样不想集成 Rust 的维护者不必这样做。但他们也不能对触及其控制范围但不改变其控制范围的代码的语言或方式指手画脚。Hellwig 反对的拉取请求 “完全没有触及 DMA 层”,Torvalds 写道(全大写强调了他的意思),而且 “简直就是它的另一个用户,在一个完全独立的子目录中”。

“老实说,你一直在做的事情基本上就是在说’作为 DMA 维护者,我控制着 DMA 代码的用途’。“Torvalds写道。

托瓦尔兹在写给赫尔维格的信中说:“我在技术上尊重你,我喜欢与你共事,”他喜欢赫尔维格 “骂我胡说八道”,因为 “需要有人站出来告诉我,我在胡说八道”。但是,Torvalds写道:“现在我要骂你的*你的*”。

这位领导者接着说,想要参与 Rust 的维护者可以参与,而且可以影响 Rust 绑定的外观。Torvalds写道,那些 “选择‘我不想与Rust打交道’的人 ”可以这样做–他后来将其形容为 “保护墙”–但他们对建立在其C语言接口上的Rust代码也没有发言权。

“换一种说法:’没有人被迫与 Rust 打交道’并不意味着’每个人都可以否决任何 Rust 代码'”。Torvalds写道,维护者也可以在中间找到空间,他们知道Rust绑定并与Rust开发者合作,但并不积极参与。

“我们为什么不这样做呢?

在早前对 “Rust 内核政策 ”话题的回应中,Kroah-Hartman 提出:”作为一个在过去 15 年多的时间里几乎看过所有内核 bug 修复和安全问题的人……我想我可以就这个话题发言。”

由于大多数 Bug 都是由于 “C 语言中愚蠢的小角情况,而在 Rust 中却完全消失了”,Koah-Hartman “希望看到 Rust 进入内核”,这样就可以将重点转移到更重要的 Bug 上。虽然 “有 3000 万行 C 代码不会在短期内消失”,但用 Rust 编写的新代码和驱动程序 “对我们所有人来说都是胜利,我们为什么不这样做呢?在对 C++ 作为一种可行的长期代码库表示怀疑之后,Kroah-Hartman 澄清了一个显而易见的观点:Rust 虽然不是 “银弹”,但它在很多方面都做得很好,尤其是对于试图处理内核棘手 API 的开发人员而言。

“是的,混合语言代码库很粗糙,也很难维护,但我们是内核开发者,我们维护和强化 Linux 的时间比任何人想象的都要长,”Kroah-Hartman 写道。“我们已经把我们的开发模式变成了一个运转良好的工程奇迹,创造出了别人无法实现的东西。添加另一种语言真的不应该是个问题,我们过去处理过更糟糕的事情,我们现在不应该放弃确保我们的项目在未来 20 多年内取得成功的想法。”

Rust 可能会成为内核中的主流语言,也可能不会。但是,将 C 语言作为主流语言,甚至积极压制与任何 C 代码的非直接交互,似乎并不是一个可行的长期战略。关于这个话题的许多讨论都注意到了以 Rust 为中心的微内核 Redox 的存在,或理论上但技术上有可能将 Linux 分叉成一个纯 C 的项目。但是,这两点都略显轻视了Linux这一主流基础操作系统的积极开发对世界的重要性。

元素周期表抱枕

本文由 TecHug 分享,英文原文及文中图片来自 As the Kernel Turns: Rust in Linux saga reaches the “Linus in all-caps” phase。

共有{173}条精彩评论

你可以看到,如今 Linus 在坚持务实的技术决策的同时,也在努力做到至少有点和善。

-- Muromec

>我发现你在抱怨你的代码的新用户时,却不断提出这些完全是垃圾的论点,这让我很苦恼。老实说,你一直在做的事情基本上就是在说 “作为 DMA 维护者,我可以控制 DMA 代码的用途”。而这一切都不是这样的。

我知道他的愤怒依然存在,只是措辞不同,攻击方式更现代(更柔和)。2025 年,我们还能这样控制开发人员吗?是的!要么接受它,要么自己去叉掉它。这种情况消失之日,就是 Linux 代码质量被千刀万剐之时。

-- 1970-01-01

我从未见过有人谈论莱纳斯的双语能力与他的愤怒问题有关。我精通两种语言,用英语说话比用母语说话更严厉、更刻薄。这可能是问题的一个因素吗?

-- philistine

有可能,但看过他的几次失误后,我不太相信这个说法。根据他的维基百科页面,他在美国生活了约 25 年,成为美国公民已有 15 年。如果他花了这么多时间与他人合作,基本上只使用英语,而且在一个以英语为日常母语的国家生活了几十年,还不能适当地掌握英语,我会觉得这理所当然比相反的情况更令人印象深刻。

-- perching_aix

这不是精通英语,他掌握得很好。这是对美国工作文化的掌握,而这是可有可无的。他之所以让美国人如此反感,是因为他的反馈很直接,美国人认为这就是愤怒。

在我(希腊人)看来,他说的都很好。他从不针对个人,他谈论的是论点/观点/问题,而不是人。“完全是垃圾论点 “是对论点的评判,而不是对人的评判,告诉别人他们的论点是垃圾,如果这是你对他们的看法的话,那是没问题的。

美国人/加拿大人/英国人会把这理解为愤怒,但在其他文化中,这只是表达自己的观点。

-- stavros

那我就该死了,因为(我遇到的老例子)……

> 关键,我已经厌倦了你不解决自己编写的代码中存在的问题,这样内核就不得不绕过你造成的问题。

……这是人身攻击,这是明知故犯的粗鲁,这是普遍的冒犯(尽管相当温和),而且我非常怀疑,在希腊语中,被告知人们对你的行为感到厌烦是 “只是表达自己的意见”。

你还必须明白,这是一封邮件。你不可能打出这样一封邮件,然后不满意就点击发送。我个人无法想象向工作中的任何人发送这样的电子邮件(甚至是短信),例如,有的时候,他们肯定是罪有应得。

是的,在有些社区和工作场所,这种交流方式是常态,而且在过去特别常见(据我所知,在蓝领工作中仍然经常如此)。美国国内外都是如此。

我不是美国人,我来自中欧。我知道 “直接了当 ”是什么样子,但这不是 “直接了当”。这就是个傻逼。在任何文化中,这样的语言都不会产生任何效果,也不会被任何文化所接受,这并不是美国人的思想病毒传播到了全世界,让人们觉得他们可以也应该有自己的交往标准。

如果说有什么不妥的话,这里最时髦的一点恰恰相反,人们似乎把把粗鲁误解为说真话当成了一种运动。就像愤世嫉俗常常被误认为是知识分子一样,这也是完全错误的,莱纳斯被洗去个人缺点是出于尊重,而不是因为他在现实中没有过错。

-- perching_aix

我也是中欧人,我不仅认为莱纳斯的语气没问题,实际上我更喜欢和他这样的人相处。我觉得这种 “注意用词 ”的文化让人感到压抑,而和那些也使用并能容忍 “坏话 ”的人在一起则让人感到自由。

-- blueflow

这最终要由每个人自己决定。我个人的感觉恰恰相反,虽然有时必须注意自己的言谈举止真的很烦人,而且有些社区出于某种原因真的过分注意言谈举止,但我真的不希望参加那些以准叛逆态度的形式无视言谈举止的社区,因为这已经深深扎根于文化之中。

对我来说,最好的两全其美的情况是,我可以自然而然地与他人打成一片,而不会出现这个问题,因为化学反应会自行产生。我非常怀念和珍惜多年来遇到的那些能与我这样合作和相处的人。我并不赞同其中的任何一个极端,而是希望能体验到更多这样的互动。

遗憾的是,随着时间的推移,我觉得这样的机会越来越少了,这要归咎于人们之间越来越多的不信任和敌意,以及如今互联网上无数其他(我认为是)功能失调的社会动态(例如,各种社区空间上的主流政治激进主义和反激进主义)。谁知道呢?

-- perching_aix

有可能,但也有可能是另一种情况。与英语相比,我用母语说的脏话要多得多。你永远不知道,也许莱纳斯总是把它调低。

-- Muromec

这是一个很好的观点,我很惊讶这个问题没有经常出现。不只是语言本身,还有语言的使用–我们当中有多少人是按照美国人通过英语教给我们的价值观来读这本书的,比如不骂人或不直接,而莱纳斯一直都是这样交流的,没有自我或善良在作祟。他直接分享自己的所见所思,然后继续前进,这本身并不一定意味着愤怒。

-- eddieroger

> 我从未见过有人谈到莱纳斯的双语能力与他的愤怒问题有关。我是双语者,用英语说话比用母语说话更严厉、更刻薄。这可能是问题的一个因素吗?

有点相关:https://www.nytimes.com/2024/05/14/magazine/native-language-…..:

> 我自己成年后开始说法语的过程就没那么快乐了。在为这本杂志的另一篇文章联系消息来源但收效甚微后,我把没有回音的邮件给一位朋友看。她温和地告诉我,我一直在对我希望采访的每个人大喊大叫。

> 与英语相比,法语语速更慢、更正式、更直接。这种语言要求一种礼貌,从字面上翻译,听起来很顺从,甚至是被动攻击。我开始收集表示礼貌交往的常用短语。“亲爱的女士,我恳请您……” “亲爱的先生,请接受我最崇高的敬意” 法语似乎总是让我的脸变得更加严肃,好像我所有的精力都集中在某些元音的准确性上。而英语则让我的嘴角泛起一丝微笑。

-- palmotea

*处理它或自己去叉(它

-- WithinReason

> 现在至少要有点礼貌

说到他,我们必须感谢他做出的巨大牺牲。但说实话,我必须同意他的观点。

开发项目的金科玉律是坚持使用一种(尽可能少的)技术,否则,你最终会开发出需要雇用不同语言开发人员的软件,或者接受那些不是其中某些语言专家的开发人员。我正在开发一个项目,直到一年前,这个项目还有一部分是用 Scala 编写的。所有不懂 Scala 的 Java 开发人员注定要在痛苦(错误和失误)中学习 Scala,或者直接忽略与系统这部分相关的任务。

-- p0w3n3d

你说得对,这通常是一条金科玉律。但规则也有例外,这似乎就是其中之一;Linux 内核现在如此庞大和复杂,而 C 语言现在又如此明显地过时了,以至于开始用 Rust 编写驱动程序的痛苦是值得的。由于内核的模块化,以及 Rust 与 C 语言的二进制兼容,这看起来是切实可行的,因为各个子系统要么完全采用 Rust 语言,要么完全采用 C 语言,尤其是在涉及新驱动程序时。

-- lambdaone

“C语言现在显然已经过时了”,笑死我了……

人们本可以围绕 Rust 催生另一个内核分支,但结果可想而知:

https://en.wikipedia.org/wiki/Second-system_effect

因此,新奇的偏见劫持了人们的推理能力,每个人都会因为多语言项目的衰败而感到沮丧。

多语言项目的本质是向构建树中注入不稳定的依赖关系。这也使得在新硬件上启动 Linux 的核心功能变得更加困难。

如果有人说这是为了学习另一种语言,那他们就是在无视人们的合理担忧。无论是否有基础支持,内核最终都应该分叉,如果人们拒绝将一个分支与炒作中编写的大量重构任务隔离开来的话。

见仁见智 =3

-- Joel_Mckay

多语言项目的本质是在构建树中注入不稳定的依赖关系

这意味着什么?

这也使得在新硬件上启动 Linux 的核心功能变得更加困难。

如果你的意思是说 Rust 并不支持 gcc 所支持的所有架构,那你就错了:

– 但这并不妨碍人们确保 Linux 也能用 LLVM 编译。

– 无论如何,gccrs 应该会让这个问题变得毫无意义,因为它将允许 Rust 代码在与 gcc 本身完全相同的架构上运行

-- tremon

> 这也会增加在新硬件上启动 Linux 的难度。

不,反正 Rust 目前只适用于不在该硬件上的驱动程序。没有 Rust,你也可以继续构建和使用内核。

目前… 也许有一天,这个讨论会变得有意义。

-- bronson

这场闹剧的起因是核心内存 API 的争论。

这一天就是今天,我的朋友 =3

-- Joel_Mckay

你说的根本不对,莱纳斯自己也说得很清楚。

这场闹剧的起因是 Rust 使用了用 C 编写的 API。这方面没有任何变化。

-- steveklabnik

是的,用 Rust 编写的驱动程序需要该 API。所以现在内核的核心部分并不是用 Rust 编写的,仍然只是特定的 Rust 驱动程序。

-- oskarkk

我的理解是,要求内核维护者在现有封装的基础上承担支持 Rust API 的额外任务。

我可能弄错了,但分支或分叉似乎是最简单的解决方案。

-- Joel_Mckay

你的理解完全错误。我们并没有提出这样的要求,而且我们也几乎立即明确指出不存在这样的期望,从而消除了这种顾虑。

https://lore.kernel.org/rust-for-linux/2b9b75d1-eb8e-494a-b0…

-- dralley

你误解了。

-- steveklabnik

“这意味着什么?

一般来说,混合语言会带来严重的长期后果。除非你重构过大型遗留系统……否则你可能无法完全理解。

也许你可以问问,为什么人们不为如此大规模的重构创建一个独立的内核分支?

“Rust 并不支持 gcc 所支持的所有架构

假设一个引导编译器甚至可以启动 Rust 或货物怪胎。人们只会转向其他选择,如果工作系统需要娱乐性的剧情,也许有人会去做一个 Rusty Linux Fork。

祝你好运 =3

-- Joel_Mckay

除非你重构过大型遗留系统……否则你可能不会完全理解。

我之所以不完全理解,是因为你没有解释清楚。我不认为这与我的工作经验有关。

-- tremon

“我不认为这与我的工作经历有关。

我知道这很有挑战性,但有些经验是普遍适用的。本讲座从组织层面探讨了这一问题:

https://www.youtube.com/watch?v=GWgRw5jiYy0

这是我现在能为你做的最好的事情了。祝你好运 =3

-- Joel_Mckay

别再挖苦我了,这不属于这里。

-- bdhcuidbebe

该讲座涵盖了多语言项目容易失败的原因。

大多数人都能在尊重他人的基础上提出不同意见。祝您愉快 =3

-- Joel_Mckay

除了… 大多数公司都提供多语言产品。众所周知,谷歌有一个多语言的 monorepo 和一个统一的构建系统。每家规模不小的公司都使用多种语言。就连 Asahi Linux 也是如此!

多语言项目比较难,但绝对没有用 C 语言开发操作系统那么难。

-- SR2Z

不确定员工流失率和取消项目的指标是否是谷歌的积极方面。

https://en.wikipedia.org/wiki/List_of_Google_products#Discon…

“绝对没有用 C 语言开发操作系统那么难”

这要看你在做什么,因为复杂性往往是沟通不畅的表现。

https://en.wikipedia.org/wiki/Conway%27s_law

该演讲嘲笑了人们在篡改他们打算稍后替换的东西时所寻找的借口。

-- Joel_Mckay

谷歌不会因为项目在技术上过于笨重而取消项目,如果你问几乎所有前谷歌工程师对内部工具的看法,他们一般都会称赞它,因为它非常好。

复杂性是与现实世界打交道的结果。操作系统与硬件对话,而硬件可能会有错误或直接的随机故障。

-- SR2Z

谷歌最初在技术上取得成功,是因为在设计时假定单个系统永远不可靠,应该优雅地故障恢复。这在过去和现在都被认为是一个安全的假设……

事实上,在任何公司的所有 IT 项目中,平均有 52% 的项目以失败告终,或者从未按设计使用过。一家光鲜的营销公司与成功的操作系统设计到底有什么关系?他们计划取代 Linux 的内部 Android 操作系统也被取消了。“所有软件都很糟糕,但有些软件还是有用的”=3

-- Joel_Mckay

顺便说一句,内核并没有使用 Cargo。

-- steveklabnik

的确,实际上更糟,因为 “x.py ”有更多的依赖关系。

-- Joel_Mckay

内核也不使用 x.py,也不与之交互。Rust 代码使用 build 来驱动 rustc,就像内核的其他部分一样。

-- steveklabnik

我认为你的假设是,两种语言都已经有了完全兼容的交叉编译器环境。

-- Joel_Mckay

驱动程序是针对特定硬件的,因此 Rust 只支持内核所支持平台的一个子集并不是问题。如果你想为 Rust 不支持的平台编写驱动程序,用 C 语言编写就可以了。

-- steveklabnik

驱动程序通常是硬件专用的,但并不总是平台专用的。例如,所有 x86 平台的 USB 设备驱动程序(但不包括主机驱动程序)在 arm 和 risc 平台上都能正常运行。内核不仅包括设备驱动程序,还包括网络等东西–高层抽象与平台的解耦效果相当好。

我不认为不支持 rust 的平台与运行 USB 主机的平台之间会有实际的交叉,但当 rust 渐渐渗透到网络子系统代码中时,你要么没有网络(之前还能运行),要么自己做一个 rust 编译器。

这可能意味着放弃平台支持。也许这些平台已经死了,但有人会说,加入 rust 客观上会让情况变得更糟。

-- Muromec

当然,问题的关键在于,这适用于你知道 Rust 支持平台的新代码。它不会 “侵入 ”到 Rust 无法支持的地方,因为那样的话,无 Rust 的构建就会崩溃。

你说得对,还有其他一些策略可以以不同的方式发挥作用,但这些策略是专门为 Rust 选择的,这样 Rust 就不会让内核牺牲旧平台。

-- steveklabnik

Rust无法支持的 “蠕变 ”不会发生

同样的论点也适用于未来的架构变化,因为 OpenBSD/FreeBSD/NetBSD 的构建要求将在未来的移植复杂性方面击败 Polyglot Linux。

我们不能两全其美… 致以最崇高的敬意 =3

-- Joel_Mckay

“如果你想为 Rust 不支持的平台写一个驱动程序,用 C 语言写就行”。

¯_(ツ)_/¯或者首先为 Rust 创建一个单独的分支。我们正在陷入循环论证的逻辑怪圈。

-- Joel_Mckay

C 语言在 1993 年就已经过时了,这就是为什么从那时起,在两种语言的选择中,我宁可使用 C++ 也不使用 C 语言的原因。

但如果真的无法绕过 C 语言,比如 UNIX 克隆相关的开发,或者某些嵌入式开发,则属于例外。

即使在使用 TypeScript 时,我们有时也不得不偶尔使用 JavaScript。)

-- pjmlp

“我宁可使用 C++ 也不使用 C

这取决于您要构建什么,因为某些语言的特定功能会增加特定任务的难度。

不幸的是,很多时候我们必须使用我们所获得的基础架构。

-- Joel_Mckay

同意,这就是为什么 “当确实无法绕过 C 语言时,就会出现例外情况……”

我工作的第一家初创公司,早在疯狂的 2000 年代,我们以自己的方式复制 AOLServer,所有的 Tcl 扩展模块都是用 C 语言编写的,原因有很多,包括在多个 UNIX 变体中编写可移植的 C 语言已经够复杂了,例如我们使用的 HP-UX aC 还不符合 C89 标准,没有必要再添加 C++。

-- pjmlp

> 人们本可以围绕 Rust 催生另一个内核分支

Linus 已经决定他的分支将是一个混合语言分支。你完全可以分叉出你自己的纯 C 内核并维护它。

-- marcosdumay

我的业余爱好内核只有 68KiB,无法在大多数冯-诺依曼机器上运行。这可能是在浪费时间,但鉴于其相对简单的特性,这是个有趣的奇特架构。

-- Joel_Mckay

然而,当权者明白这一点,并推断出防止有漏洞的新代码进入内核的好处太诱人了,因此不能忽视。

-- braiamp

人们并没有为大规模重构建立一个新的内核分支选项,是吧… 相反,理想主义者劫持了一个成功的项目,并让有合理顾虑的人滚蛋。分叉是健康生态系统的一部分…

祝你好运 =3

-- Joel_Mckay

Linus torvalds 是这里最大的理想主义者。

-- imtringued

在我上一份工作的一家 FAANG 公司,我们用 Kotlin 编写了一个 Android 应用程序,管理层以他们的智慧决定采用时髦的新事物 React Native,并开始用 React Native 编写新的/某些功能。

多年后,情况如何呢?我们有一部分代码库使用 Kotlin,由专门的本地/Kotlin 开发人员负责;还有一部分代码库使用 RN,由专门的 RN/JS 开发人员负责。

每当出现一个 Bug,团队之间就会不断争论谁拥有这个 Bug、Bug 来自代码的哪个部分(本地还是 JS)、谁对这个 Bug 负责。很多时候甚至没人知道,因为每个团队现在只熟悉应用程序的一部分。

团队之间各自为政。每个团队都在尽力保留代码库–本地团队试图阻止 JS 团队将整个代码库变成 JS 代码库,而 JS 团队则试图将尽可能多的代码库改成 JS 代码库。本地团队争论 JS 功能为什么不好,JS 团队争论用本地语言编写的好处。不断地来来回回。

现在,没有一个团队能从整体上了解应用程序是如何工作的。应用程序的很多部分都由其他团队使用其他语言拥有和维护。让开发人员 “拥有 ”应用程序、了解其工作原理、全面了解整个产品的能力迅速下降。

每当有新功能出现,都会有关于它应该是原生还是 RN 的争论。原生团队指出性能和观感方面的问题,RN 团队指出代码共享/快速开发的好处。来来回回不断。通常情况下,谁的管理者最有说服力,谁就能获胜,而不是以技术优势取胜。

与用一种语言编写、由开发人员团队开发、拥有并了解整个应用程序的一个应用程序相比,我们的新设置是否让我们最终获得了更好的应用程序?不,我不这么认为。

与 Rust/C 相比,我们感觉情况很相似。

-- thegrim33

除了决定用哪种语言构建新功能的选择问题(这需要一个明确的政策),我不明白为什么维护一个混合语言的代码库一定会很糟糕。

我现在的工作也是在 FAANG,我所在的团队(虽然是 SRE 团队,不是开发团队)拥有中等规模的 C++、Go、Python 代码库和少量 Java 代码库。每种语言都有 “专业 ”的人员,但每个人一般都有足够的能力至少阅读并大致理解其他语言的代码。

当然,有时问题出在语言的特殊语义上,需要专业人员来处理,但也有很大一部分是任何人都能发现的逻辑问题,或者是任何人都能做出的小改动。

你所描述的情况中的关键问题似乎是团队中的功能障碍,即为自己一方争辩,而不是像其他技术决策一样,在选择语言时应以大局为重。我认为这部分源于领导层对如何评估决策的认识不清。理想情况下,您应该在快速开发和一致性之间选择优先级,并以此为指导做出决定和选择语言。

当你的代码库扩展到一定程度后,各自为政是不可避免的,最好是专注于建立系统树,以及谁负责什么。但是,这并不意味着领导者可以只关心自己的系统。需要有人了解事情的大概,至少能隔离各个相连系统之间的问题,即使他们不是所有系统的专家。

-- ratorx

在 “FAANG ”名单中,我们可以排除苹果公司(原因显而易见)和亚马逊公司(原因显而易见),因为从其移动应用程序糟糕的可用性可以看出,他们的原生代码为零。谷歌使用 RN 吗?他们的 Flutter 堆栈似乎不太可能。

这是在 Meta 发布的吗?我怀疑 iOS 的 FB 应用程序和 Insta 使用的是 RN,那么 FB messenger 是否也使用 RN 呢?

-- fingerlocks

> 我怀疑 iOS FB 应用程序和 Insta 正在使用 RN

https://reactnative.dev/blog/2017/08/07/react-native-perform…

> React Native 在 Facebook 系列的多个应用程序的多个地方都有使用,包括 Facebook 主应用程序的顶层选项卡。我们这篇文章的重点是一个高度可见的产品–Marketplace。

-- steveklabnik

虽然我认为你关于多语言/框架项目中出现的一些困难的观点是公平的,但每当有人把 Rust 说成是 “时髦的新事物 ”时,我都会翻白眼。

Linux 内核的首次 “发布 ”是在 1991 年,1994 年达到 1.0 版本,2004 年的 2.6 内核可以说是第一个现代版本。Rust 的 1.0 稳定版发布于 2015 年,距今已有 13 年。现在的职场人士中,有一些人在 Rust 首次发布时还是初中生。从那时起,Rust 已经发布了 85 个次要版本和三个后续版本,建立了一个开发者社区,并得到了大型机构在关键业务代码方面的机构支持。

即使将 1991 年作为实际的首次发布日期,Rust 作为一种稳定的语言也已经存在了 Linux 公共开发历史的三分之一以上(当然在此之前还有多年的开发历史)。因此,我认为把它归入 “时髦的新事物 ”一栏有点不公平。

-- qchris

我干这行已经 20 多年了,还是第一次听说这条 “黄金法则”。我想我们都做错了……永远都在用各种语言编写我们的后端(随你选)、前端(TS/JS)和查询(SQL)。

-- GiorgioG

我主要看到的是前端的语言混合。后端似乎最终要么被完全移植到一种新的(兼容的)语言上,要么被移植回实验性的新语言上。也许前端开发人员更多才多艺是因为他们不得不这样做,因为框架和基础规范在他们脚下不断变化。

甚至许多后端开发人员似乎也对 SQL 等语言望而却步,因为他们对这些语言不太适应。这本身并不是坏事,在查询中犯一个小错误很容易就会导致数据库崩溃,这只是我的个人看法。

-- jeroenhd

在我 30 年的后端工程师生涯中,我从未在单一语言的代码库中工作过。

那种认为语言不能混用的想法完全是无稽之谈。如果有人跟我说这是有可能的,我会非常好奇他们是通过什么疯狂的折衷来达到这个目的的。

-- kasey_junk

我认为,如果所有开发人员都只掌握一种语言,而且将来也没有兴趣学习更多语言,那么在代码库中偏好单一语言是有道理的。但这并不一定是金科玉律。

不过,在我的工作中,我见过很多拥有各种兴趣和经验的开发人员只掌握一两种语言,如果这就是贵公司的人才库,那么单一语言代码库似乎是个不错的主意。

当然,这忽略了所有脚本语言(makefile/bash/Python/XML)的使用,根据我的经验,这些语言被视为构建工具的怪癖,而不是产品的一部分。

-- jeroenhd

还有互补与竞争: C++/python(pytorch、itk、ROS)或 Go/js(默认网络协议栈)不会争论什么属于什么语言–react/swift 或 c/rust 代码库则没有这样的天然分区。

-- QuadmasterXLII

> 也许前端开发人员更多才多艺

考虑到他们连煮咖啡都要用 Node,我认为这种说法非常不准确。

-- toyg

如果你看一下这种混乱是如何开始的,前端有跨站脚本,因为 html 允许你从任何地方注入更多的 javascript;后台有 SQL 注入,因为你必须将输入从一种语言翻译成另一种语言,而这些工具会不遗余力地将数据解释为命令。

现代网络是一个巨大的烂摊子,所有的安全功能都是通过黑客攻击实现的,甚至连远程安全都做不到,而在电子产品进入桌面的那一刻,我们就遇到了跨站脚本攻击,每个人都可以通过插件说明页面读取本地文件。如果说有什么不妥的话,它就是事情发展到何种程度的终极证明。

-- josefx

像我这样在ERP/bussines应用程序中工作的人使用的语言就更多了。

我在我的小项目中使用了大约 20 多种语言(主要是单机版),现在我有了

* Rust

* Kotlin

* Swift

* Html

* Sql,有各种不同的版本: Postgres, Sqlite, Sql Server, Firebird, DBISAM, MySql

* Go

* FreePascal

现在我的语言越来越少。

人是灵活的。

-- mamcx

这真的是 “黄金法则 ”吗?

我参与过很多跨语言的代码库。虽然拥有语言或部分的专家非常有用,但一个人不需要成为专家也可以为其他语言编写的部分做出有意义的贡献。当然,内核开发人员级别的程序员应该很容易就能学会 Rust 的基础知识。

共享业务逻辑或渲染代码与特定平台封装代码的用例很多,例如,C++ 或 Rust 内核与 Swift、Kotlin 和 TypeScript 封装。很多高级语言都有用于快速实现的底层 API,如 CPython、Ruby FFI 等。反过来,很多原生代码引擎也有 Lua、Python 等脚本 API。

-- wffurr

我不知道这是金科玉律还是常识。

如果我们的测试框架是用 Python 编写的,那么用 Perl 编写一个封装程序来为你的功能编写测试代码,因为你对它更熟悉,这在我看来是错误的做法。

但如果用 Ruby 编写一个 FluentD 插件,就能解决相同底层中的一个重要问题,那么额外的语言可能是值得的。

一切都需要权衡利弊。

-- w0m

我认为语言的数量并不那么重要,重要的是所选语言/框架的支持程度/稳定性如何,以及所选工具是否提供了良好的 DX 和 UX。简单地说……使用 5 种支持良好的语言/框架(如 C、Rust、Java、Python、现代 React/TS)的项目要比使用 3 种晦涩难懂/不断变化的语言/框架(如 Scala、Flutter、Groovy)的项目好得多。

总之,我是 Rust 的忠实拥趸,一般认为在内核和其他底层应用中使用 Rust 对每个人都有好处,与其他项目相比也不会增加太多复杂性。但我也可以看到,2030 版的 C 语言添加了借用检查器和更多可比较的宏特性,而 Rust 则随着时间的推移逐渐从人们的视线中消失,开发人员不得不逐渐取消在传统 C 语言项目中使用 Rust 的做法。

-- pseudocomposer

这可能吗?C 能否添加借用检查器?老实问,我不知道任何东西是如何工作的

-- chamomeal

C 语言非常重视向后兼容性,因此它添加的任何内容都必须经过用户同意(这并不妨碍某些人试图提出严重破坏 C 语言的改动,但这就是生活)。

像借用检查器这样的东西是可以添加的(C 语言委员会中也有人愿意看到它)。不过,Rust 的 “共享 xor 可变 ”规则对 C 语言来说可能太强了,所以你需要找到一些能解决大量内存安全问题的较弱模型(也许表达指针所有权和某种形式的失效就足够了,但这只是我的一些猜测)。有兴趣的人现在主要关注的是边界检查,而不是借用检查器。

-- jcranmer

理论上可以。在实践中,我会感到震惊。举个例子,Rust 的内存安全规则从根本上说是建立在泛型之上的,而 C 语言没有泛型。因此,要复制 Rust 所做的一切,他们需要首先做到这一点,而这是对语言的巨大改变。

C++ 确实已经有了泛型(好吧,模板,但你知道的),所以在那里移植会更容易,但仍有大量工作要做。https://safecpp.org/draft.html 解释了如何实现这一点。

-- steveklabnik

我觉得不太可能。C 语言基本上是建立在内存别名和指针运算基础上的:每个变量都表示为内存中的一个位置,但不能保证每个内存位置只表示一次(可能有很多变量指向同一个内存地址)。Rust 借用检查程序需要的保证则恰恰相反:每个声明的变量都能完全控制其内存位置,如果两段代码需要共享内存,则需要一个明确的协议来授权访问。

指针在 C 语言中并不罕见。这种机制几乎无处不在:访问数组值、逐个引用参数传递、函数输出参数、字符串操作。C 语言中也没有函数纯粹性的概念,因此无法在函数定义中保证函数不会越界。当然,在 C 语言程序中可以或不可以做什么,有一些安全的编码约定和规则,但要从根本上证明某个内存位置只能通过某个变量访问,只能通过穷举式地运行程序–或将自己限制在 C 语言的一个子集–来实现。

但是,当你只允许使用 C 语言的一个子集时,它就不再是 “带有借用检查器的 C 语言 ”了,尤其是考虑到指针在标准语言功能中无处不在。它很快就变成了 “我们削弱 C 语言,因为我们需要更多的保证”。引用 D 语言手册[0]中的一句话:要保证内存安全,就必须禁止使用:

  - Casts that break the type system.
  - Modification of pointer values.
  - Taking the address of a local variable or function parameter.

[0] https://dlang.org/spec/memory-safe-d.html

-- tremon

> C 语言基本上是建立在内存别名基础上的

此外,C 语言确实有内存别名规则,但包括内核在内的许多项目都关闭了这些规则。尤其是 Linus,他认为不值得使用这些规则。

这些规则与 Rust 的不同,Rust 也拒绝了这些特殊规则。

> 引用 D 手册中的一句话[0],为了保证内存安全,你需要禁止

需要说明的是,这是 D 语言的列表,而不是一般意义上的列表。Rust 允许你获取局部变量或函数参数的地址。

-- steveklabnik

> C 确实有别名规则

如果你指的是 gcc 的 -f[no-]strict-aliasing(严格别名)选项,那么这更多地是关于类型兼容性,而不是限制一般内存别名的范围。如果你指的是其他方面,我很有兴趣了解更多信息。

> 这是 D 语言的列表,不是一般的列表

是的,我知道。但这是我能想到的第一个关于类 C 语言内存安全的权威资料。我不认为这个列表对 C 本身有什么错误,只是可能不够详尽。

> Rust 允许你获取局部变量的地址

是的!但回到前面的问题:在 Rust 中,你之所以能做到这一点,特别是因为该语言在变量和所有权方面有定义明确的生命周期语义。因此,Rust 可以保证:a)指向内存位置的指针不会超出内存分配本身的范围;b)当两个变量/指针指向同一个内存位置时,编译器会强制执行访问和更改该内存的协议。

-- tremon

> 那么,这与其说是在限制内存别名的范围,不如说是在限制类型兼容性。

这是关于限制指针别名的能力。C 标准甚至有这样的括号:

> 本列表的目的是指定在哪些情况下可以或不可以对对象进行别名。

你说得对,这是一套相当狭窄的规则。列表中只有六个项目。但它仍然是一条别名规则。

-- steveklabnik

> C 能否增加一个借用检查器

据我所知,在保持与旧代码兼容的同时添加借用检查器是不可能的。你必须为注解等添加新的必要语法。

-- porridgeraisin

莱纳斯电子邮件的直接链接:https://lkml.org/lkml/2025/2/20/2066

-- monideas

这是一个有趣的讨论。当你从一种东西慢慢迁移到另一种东西时,总会有分歧。

有趣的是,C 代码和 Rust 代码之间的差异并不是可以忽略的。你会失去那些根本不想或无法花时间去研究新语言复杂性的开发人员。你将暂时拥有一个两个世界相互碰撞的代码库。

我不知道他们回过头来会如何看待今天所做的决定。

-- zubspace

Rust 很有可能在未来几年内仍将严格控制在驱动程序方面。就目前而言,这是一个非常自然的谢林栅栏,其好处是相当可观的,既能提高驱动程序的质量,又能降低贡献驱动程序代码的难度。此外,它还能间接提高核心代码和文档的质量,因为它能迫使许多不够规范和复杂的 API 合约变得更加严谨(并有望得到简化)。这也正是 RfL 与守旧派之间产生摩擦的主要原因之一:为了合理调用许多内核 API,你 “需要知道 ”的事情有很多很多,而这与试图在这些 API 上编写安全(r)的 Rust 抽象是格格不入的。

-- Sharlin

后者的一个例子:drm_sched

https://vt.social/@lina/113051677686279824

-- Tyr42

lkml 戏剧的链接是什么?

-- Vilian

> 这与在它们之上编写安全的 Rust 抽象并不相符。

或者只是使用这些内核 API。

-- renewedrebecca

我不认为完全改用 Rust 代码是可以实现的。我猜一些更老或更接近金属的部分会继续使用 C 语言,但流量更大、进化更快的部分在使用一段时间后会变得更生锈。

gccrs 将允许使用 GCC 工具链一举构建整个系统。

如果银行仍在使用 COBOL 和 FORTRAN,在我看来,这将是最有可能实现的。

-- bayindirh

> 我猜一些更老或更接近金属的部分会留在 C 语言中

我想最大的原因是,C 语言程序员更有可能接受过培训,在很多情况下都知道汇编会是什么样子,或者非常清楚优化编译器会如何优化。

这提醒了我,我需要用 Rust 做一些非繁琐的嵌入式项目,看看它在这方面的表现如何。我不确定抽象是否会妨碍工作。

-- leonheld

在编写了一些对性能敏感的非繁琐 C/C++ 代码之后,你会感觉到这些代码在真实金属上的表现。例如,我就有这种直觉。我从未深入到生成 ASM 的层次,但我只需注意我在 C++ 中的操作(最小分支、将分支偏向某一边等),就能获得 ~80% 的理论 IPC。

因此,我认为如果你用 Rust 做同样的事情,你也会有这种直觉。

我有个朋友是写嵌入式 Rust 的,他说 Rust 还没有 C 语言那么流畅。我认为 Rust 已经完成了前 90% 的成熟期,还有 90% 的成熟期。

-- bayindirh

我全职编写嵌入式 Rust,可以说在 C 语言中能做的事,在 Rust 中没有做不到的。当然,工具/框架要成熟得多,但寄存器访问的 PAC(也许还有一点社区维护的 HAL)和 RTIC 这样的框架的组合几乎就是我所需要的全部。

-- sakian

鉴于 Rust 类型系统所做的大量繁重工作,我并不相信生锈的 Rust 与 C 语言一样可以用大脑编译。这种代码很容易在脑中编译。

-- pclmulqdq

这不是大脑编译能力的问题,而是习惯了特定编译器对你大脑编译的代码的处理方式。

因此,我脑中有一个代码模型,而这个代码在被你最喜欢的工具链编译后,也有一个现实世界中的行为。这两种情况都做过足够多的次数,你就会对自己的代码和编译器对你的代码的行为都有一种感觉。

当你更换语言时,这种感觉就会消失。例如,我可以用脑编译 Go,但编译器会添加其他功能,如 GC 和空指针保护(如果在返回函数后遇到空指针异常,则将局部变量带入堆)。习惯这些需要时间。Rust 也是如此。

-- bayindirh

> 我认为最大的原因是,C 语言程序员更有可能在很多情况下知道程序集是什么样子的,或者对优化编译器将如何优化非常了解。

这是 Hellwig 的反对意见在我看来唯一有意义的地方。显然,内核模块内部的边界不是 REST-API,在 REST-API 中,提供者和客户端是完全分离的。在这里,我认为 DMA 模块及其 API 消费者都被编译成了单片二进制文件,因此如果对 API 消费者的假设发生变化,就会影响模块本身的编译方式。

-- xg15

我用 C 语言完成了一个非复杂的嵌入式项目(四旋翼飞行器固件)。这种语言并不碍事,但我不得不在很多地方编写自己的工具。

-- the__alchemist

有哪一层 C 语言是最佳选择?对于 ASM 来说太高级,而对于 Rust 来说太低级?(这不是我的领域,所以是个真诚的问题)。

-- flir

很多人仍然错误地认为,C语言仍然是映射到汇编指令的琐碎工具,因此在理解这一点很重要的领域,C语言比C++和Rust更有优势–但实际上,这种重要性被夸大了,现代C语言编译器在高优化级别上的优化能力非常强,很多C语言开发人员如果只看一小段代码,就会对产生的结果大吃一惊。

高级系统语言的一半意义就在于能够表达程序的_效果_,并让编译器找出如何高效地实现这些效果(C++ 将此称为著名的 “假设法则”,即编译器可以做任何事情来进行优化,只要它在可观察到的效果方面表现得就像没有进行优化一样–C 语言也是如此)。我认为,从语言的角度来看,C语言已经没有比C++或Rust语言更强的地方了。如果生成的代码必须以非常特殊的方式工作,那么在任何情况下你都需要使用汇编语言。

Rust 真正欠缺的是在嵌入式环境中使用的成熟度,我所说的成熟度主要是指嵌入式目标的工具链使用起来比较麻烦(或者根本不存在),以及一些有用的抽象概念在这些环境中对于安全的 Rust 来说并不存在(但 C 语言中本来就不存在这些抽象概念)。

-- chippiewill

通常情况下,C++ 的强类型系统意味着如果将 C 代码用 C++ 编译器编译,运行速度会更快。虽然速度更快的部分原因是 C++ 允许编译器做出可能是错误的假设,因此在优化之后,您的代码有可能出错(在我看来这种可能性非常小)。C++ 通常有更好的抽象,如果使用这些抽象,C++ 的速度将比 C 更快。

如果 Rust 不能因为更好的抽象而比 C 语言编译得更快,那只能说明编译器在优化方面需要更多的工作,而不能说明 Rust 不能更快。编写优化器很难,需要很长时间,所以我认为 Rust 会落后于 C。

请注意,以上是关于真实世界的基准测试,不太可能达到 0.03% 的速度差异–需要非常特殊的设置才能测量出这些差异,而简单的代码修改就能轻松达到几百个百分比的差异。普通的微基准测试一般都没有大到足以让类型系统产生影响的程度,因此,尽管在实际问题中,C语言并不是第一位的,但却经常被显示为第一位。

-- bluGill

Rust 从设计上就是一种系统编程语言;位操作完全在它的职责范围之内,我想不出内核中有什么是 Rust 做不到而 C 可以做到的。如果你想非常非常严格地控制机器指令的生成,那么无论如何,你都必须使用汇编语言,无论是 Rust 还是 C。

-- lambdaone

在 UNIX 作者修改他们对 UNIX v3 应该是什么样子的想法时,UNIX v2(又称 Plan 9)已经有了 Alef 的首次尝试。

甚至是 C++,很多人都忘了它也是在贝尔实验室的 UNIX 小组诞生的,主要原因是 Bjarne Stroutroup 再也不想重复他将 Simula 降级为 BCPL 的做法,因此带类的 C 最初是为贝尔实验室在 UNIX 上的分布式计算研究项目而设计的,Bjarne Stroutroup 当然不会重复之前的经历,这次是用 C 而不是 BCPL。

-- pjmlp

我不知道你说的 “为……留下位置 ”是什么意思。在 Unix 上,Perl 和 Tcl 是有用武之地的。因此,我们才有了 Perl 和 Tcl。

如果你的意思是,C 语言应该把所有的用户空间编程都让给 Perl 和 Tcl,我强烈反对。首先,这个观点自相矛盾;Perl 是一个用户空间程序,而它是用 C 语言编写的。其次,对于超过 100 行的程序,C 语言比 Perl 更易于维护。

更重要的是: 在 Unix 平台上,开发者语言有一个自由市场,C、Perl、Awk、Sed,可能还有其他几种语言,都可以免费使用(言论自由和啤酒自由)。在这些语言中,C 语言胜出,成为大部分严肃开发都使用的语言。为什么 “应该 ”发生其他事情呢?如果开发人员认为 C 语言比 Perl 更适合他们要写的东西,他们为什么不使用 C 语言呢?

-- AnimalMuppet

我就是这个意思、

“哦,那是很久以前的事了。C 语言问世后,我就有点停不下来了。那是一个很大的打击。我们在优化和转换方面取得了巨大进步。我们解决了一个又一个棘手的问题。C 语言问世后,在一次 SIGPLAN 编译器会议上,贝尔实验室的史蒂夫-约翰逊(Steve Johnson)和我们的一位员工比尔-哈里森(Bill Harrison)进行了一场辩论,前者支持 C 语言,而后者正在进行我当时支持自动优化的一个项目……辩论的焦点是史蒂夫辩护说不必再构建优化器了,因为程序员会处理它。这其实是程序员的问题….。塞伯尔 如果 C 语言仅限于操作系统内核使用,你认为 C 语言合理吗?艾伦 是的。那就没问题了。事实上,你需要这样的语言,专家们可以在没有大瓶颈的情况下进行真正的微调,因为这些都是需要解决的关键问题。到 1960 年,我们已经有了一长串了不起的语言: Lisp、APL、Fortran、COBOL、Algol 60。自 C 语言发展以来,我们已经严重倒退。C 语言摧毁了我们在自动优化、自动并行化、高级语言与机器自动映射等方面推动技术发展的能力。这也是编译器……基本上不再在高校中教授的原因之一。

— Fran Allen 采访,摘自:Peter Seibel. 工作中的编码员: 对编程技术的思考

C 语言的胜利与其说是因为它的技术能力惊人,不如说是因为它没有其他编译语言。

更有甚者,当 Sun 开创了 UNIX 开发工具需要额外付费的潮流时,它只包含 C 和 C++ 编译器,如果需要 Fortran 和 Ada 等其他编译器或集成开发环境,则需要额外付费。

其他 UNIX 供应商也很快跟进。

-- pjmlp

谢谢你的解释。

但我以前也见过这句话,甚至是你说的。我当时不信,现在也不信。

C 的存在丝毫不会妨碍人们研究弗兰-艾伦所说的那种问题。什么都没有!其他语言依然存在。思想依然存在。关心这类问题的人依然存在。去做你的研究吧,没人阻止你。

实际情况是,想做研究(和/或支付研究费用)的人越来越少。C赢得了人心;而弗兰-艾伦(和你)却在哀叹自己喜欢的一方输了。

值得一问的是,即使 Ada 或 Algol 或其他软件需要额外的成本,为什么它们不值得额外的成本?如果它们真的那么好,为什么大家不买来用呢?

事实是,人们认为它们不够好,不值得购买。为什么不值得?人们不再认为这些自动优化研究途径值得追求。为什么不值得?大学在教 C 语言,而 C 语言对他们来说是免费的。但大学有足够的钱来支付其他语言的费用。但他们没有。为什么不呢?

答案不能仅仅是 C 语言是免费的,而其他语言是收费的。C语言赢得太彻底了–尤其是如果你声称其他语言更好的话。

-- AnimalMuppet

更糟的就是更好的,大多数人都很吝啬,如果柠檬是免费的,而多汁甜美的橘子却必须购买,那么无论如何,他们都会喝下苦涩的柠檬水,最终味道会很好。

大学总是在与预算作斗争,有些大学甚至无力维持图书馆的运转,无法提供足够好的最新书籍。

-- pjmlp

为什么不呢?我就是看中了它的价格。

那年我 12 岁。C 是免费的,替代品却不是。当我有能力花钱买一个的时候,我已经写 C 语言十年了…

如今,我是十英尺长的棍子都不会碰它。

-- Filligree

> 实际情况是,想做研究(和/或支付研究费用)的人越来越少。C赢得了人心;弗兰-艾伦(和你)正在为你所偏爱的一方的失败而哀叹。

算是吧。C 语言的崛起部分归因于通用硬件的崛起,而通用硬件的崛起使得人们不再需要优化器来利用硬件的特殊功能。如果没有矢量硬件可以运行,自动矢量器也就没什么意思了。

不过,当 Java 成为一种重要语言时,许多先进的优化和分析技术也开始复兴。例如,在 C 语言中,别名分析是微不足道的–要么你根据相当局部的信息明显地证明它们不存在别名,要么你的别名分析(无论你如何努力提高其灵敏度)就会放弃,保守地将其归入 “一切都必须别名 ”堆中;中间地带并不多。

-- jcranmer

直接用比特敲击、移位、比特掩码等方法对硬件编程。在 ASM 中进行大范围编程太麻烦,对 Rust 甚至 C++ 来说又太低级。

另外,对于这类事情,你有 “确定性 C ”风格,它能保证每天都按你的方式行事。

给每个回答问题的人: 这是我在与业余和专业编写 Rust 的人聊天时了解到的。这并不是 “Rust不好 ”之类的偏见。普遍的共识是,C 语言更贴近硬件,可以更好地处理硬件的怪异之处,因为你可以做一些 “看似危险 ”的事情,而硬件需要这样做才能成功初始化。老式硬件是很挑剔的,记住这一点就好。另外,如果有人想知道的话。当 gccrs 可用时,我就会开始学习 Rust。我不喜欢 LLVM,但对 Rust 没有任何问题。

-- bayindirh

> 对于 Rust 甚至 C++ 来说,“…… ”都太低级了。

我很想听听为什么要这么做。在 Rust 或 C++ 中进行位操作并不比在 C 语言中困难。

-- dralley

你的意思可能是 “C++98 的 C 兼容子集”。

-- friendzis

我能想到的原因有两个。

由于 C 语言比较简单,C 编译器输出的汇编往往更容易预测。这在编写外来硬件的驱动程序时很重要。

有时,要做一些事情,比如制作一个性能良好的环形缓冲区(不需要 vec dequeue),无论如何你都需要使用不安全的 rust 语言,而这在我看来只是增加了 rust 语言的复杂性,却没有带来任何好处。

我不认为使用 C++ 比使用 rust 语言有什么好处,除了它能更容易地与 C 代码对接。在我看来,这并不重要。

-- dartos

> 由于 C 语言比较简单,C 编译器输出的汇编往往更容易预测。

这种假设的通常结果是,用户向编译器抱怨它没有生成预期的汇编代码,编译器对此不予理睬,因为他们从未保证过任何特定的汇编输出。

对于人们在使用特殊硬件时希望得到的隐式汇编保证,情况尤其如此。例如,编译器会很乐意将加载和存储合并为更大的加载/存储,所以如果需要将两个相邻字节的加载作为两个字节加载而不是一个 16 位加载,那么就应该使用内联汇编而不是 C 代码。

-- jcranmer

我并不是说每个 C 语言编译器都是完全可预测的,但由于它是一种更简单的语言,所以它的可预测性应该总是高于 Rust,除非进行了神秘的优化。

我同意,如果有人真的关心汇编,他们应该手工编写汇编。

-- dartos

> 我并不是说每个 C 语言编译器都是完全可预测的

没有一个 C 编译器是可预测的。首先,编译器会进行神奇的优化。

然后是未定义行为(Undefined Behavior),在 C 语言中,这几乎是一种保证,你会在不同的编译器、目标、优化级别和月相之间遇到不一致的行为。

在 Rust 中,可以大量使用 .iter 来避免绑定检查,如果你想要自动矢量化,可以使用大量固定长度的数组,看看 LLVM 是如何自动矢量化的。这需要时间适应,但如果你关心 SOURCE -> ASSEMBLY 的转换,那么几乎所有语言都会这样做。

-- Ygg2

> 由于 C 语言比较简单,C 编译器输出的汇编往往更容易预测。

这似乎并不正确,因为存在 UB、不同平台和优化级别。

> 有时,要做一些事情,比如制作一个性能良好的环形缓冲区(不需要 vec dequeue),无论如何你都需要使用不安全的 Rust 语言。

如果你用 Rust 写一个数据结构,它就会把不安全的繁琐部分封装到一个更安全的外壳中,并根据需要提供不安全的访问。当然,Vec、VecDeque 和环形缓冲区的内部工作原理是不安全的,但用于修改它们的 API 却不是(在任何不安全方法中都说明了安全访问的前提条件)。

这样做的目的是尽量减少不安全方法的数量,而不是彻底消除它们。

-- Ygg2

代码的自动矢量化很难预测,或者说,当人们掉进优化器会利用的 UB 雷区时,代码的自动矢量化也很难预测。

-- pjmlp

到底为什么对 Rust 来说太低级了?

-- hkwerf

> 对 Rust 甚至对 C++ 来说都太低级了。

这对我来说没有任何意义,你能解释一下原因吗?

-- metaltyphoon

“C语言更接近硬件”[需要引用]

这句话在 50 年前可能是对的,但我不相信它在 25 年前是对的,要让我相信它在今天是对的,还需要很多努力。

-- andrewaylett

Rust 在这方面做得还可以,但通常使用一些工具来使寄存器和位标志操作看起来更像正常的 Rust 函数,效果会更好。唯一需要的 asm 将是启动设置,以便运行 rust(或 C)。

-- bfrog

老实说,如果需要进行位操作,我现在会选择 Rust 而不是 C。Rust 拥有比 C 更丰富的位原语集。

-- jcranmer

也许是密码基元和数学内核的通用实现。

-- SSLy

我认为前者可以从强大的类型系统中获益,而后者则可以从(强制的)严格别名中获益。

-- hkwerf

> 我不知道他们回过头来会如何看待今天做出的决定。

决定不是今天做出的,今天(或者说几天前)发生的事情是莱纳斯斥责一个 C 语言维护者不遗余力地坑害 Rust 开发者。在此过程中,Rust 开发人员也被指行为低劣。

运行 Rust 实验的决定可以(也正在)受到批评,但如果你允许人们故意破坏实验过程,那么你也将失去大量的开发人员。

-- pyrale

在这个问题上总是会有一些争吵和尖叫。我认为这是一个合理的中间立场

-- Havoc

是很合理,但把纯属常识的东西称为 “中间立场 ”就太宽泛了。

-- baq

这是另两个现实极端之间的中间地带,这两个极端是 “子系统维护者必须理解并支持 Rust 与其 API 的绑定 ”和 “子系统维护者可以否决 Rust 与其 API 的绑定”。

-- mort96

如果有人在认真论证前一种立场,我还没有看到。

-- andrewaylett

我也没看到有人主张前者,但我认为有些维护者担心事情会朝着这个方向发展。

-- mort96

作为 C 语言的维护者,你应该关心接口的另一方是如何实现的,即使你并没有积极参与编写该代码。出于软件质量的考虑,我认为制定一项政策,让维护者可以简单地假装另一方不存在是不合理的。

-- macspoofing

这取决于维护者;如果他们不了解 Rust,那最好还是不要参与。他们仍然有责任为自己的子系统设计出最好的 C 语言接口,而这正是内核的大部分交互对象。这让 Rust 的拥护者肩上的担子更重了,因为他们相信这项任务是可以完成的。

至于你对代码质量的担忧,现在的情况已经完全一样了。维护者要对自己的代码负责,而不是对调用它的代码负责。而 Rust 代码只是另一个用户。

-- tux1968

>他们仍然有责任为他们的子系统设计最好的 C 语言接口,而这正是内核的大部分交互对象。

如果 Rust 代码是你的界面的重要或主要消费者……作为 API 设计者,你肯定会对 API 的使用方式产生兴趣。

我并不是说你成了 Rust 绑定的所有者,或者你必须执行代码审查,或者你对模块有否决权……但你不能假装 Rust 不存在。

-- macspoofing

要对 Rust<>C 绑定提供良好的反馈,就必须非常了解 Rust。这需要对 Rust 的安全要求有深刻的技术理解,还需要对 Rust 的习语和设计模式有一定的了解。

不关心 Rust 的 C 语言维护者可能会对 Rust API 有意见,但这并不是一回事:)

如果 C API 维护者了解 Rust,交流起来会容易得多,但这并非必要。Rust 存在于 C API 的世界中,而这些 API 都不是为 Rust 设计的。

Rust 开发人员可以将他们的需求翻译成 C 语言。C API 需要记录内存管理和线程安全要求,但这可以用任何语言来实现。

-- pornel

这让厨房里的厨师太多了,更糟糕的是(!)稀释了你的时间和对你所熟悉的那部分代码的理解。你需要相信你在其他代码领域的同事,他们会在没有你的情况下做出正确的决定,而你只需要专注于你所熟悉的领域。让其他人做他们自己的工作,不要对他们进行微观管理。把时间花在自己的事情上。

有时,其他团队被证明是无能的,你不得不做他们的工作。但这种情况并不多见。因此,相信其他团队能做好他们的工作(包括尝试一些你不喜欢的东西)是一条很好的规则。

-- bluGill

API 是合同的边界。只要文档齐全并满足其后设条件,它就可以在任何地方实现。计算就是在这样的抽象层中蓬勃发展的。

-- MontagFTB

当然,这对于愿意这样做的维护者来说是最理想的(有几个维护者愿意这样做),但对于那些不关心也不能强迫他们关心的 C 语言开发人员来说,这是一种务实的妥协。并不是每个人都必须参与双方的工作。

-- dralley

>这是一种务实的妥协。

没错,就是这样。这是一种 “务实的妥协”,是为了回避重大的内部文化和哲学问题(而不是技术问题)。你基本上是在告诉许多 C 语言维护者,他们可以假装 Rust 不存在,即使 Rust 代码可能是该 API 的主要用户。这是一个可行的解决方案,但并不是一个理想的解决方案–这让人有点难过。

-- macspoofing

在接口上打孔是个坏主意。而且可能是最糟糕的办法。你’应该’忽略接口的另一侧。如果这样做行不通。就在那边解决问题(自己解决或找到代码持有者),而不是从你这边尝试变通。或者,如果总是需要在两端都进行更改,那就说明你的界面设计不合理(因此总是把两端粘在一起,而不是分开)。

我非常讨厌有人自以为聪明,在界面的另一端解决问题。最终的结果总是,你需要同时了解解决方法和原始错误,否则你甚至无法读懂它。

-- mmis1000

你应该关心它是否可用,但他们如何使用它与你无关。如果有人想用 usb 驱动程序连接硬币电机来制造振动内衣,那就与你无关了。你关心的是你的驱动程序是否符合规格要求,是否可以连接。

因此,如果有人想用 Rust 编写软件,但只使用 DMA 驱动程序,那应该没问题。莱纳斯完全正确。

-- bena

>您应该关心它是否可用

是的。这就要求我们不能完全忽略 API 的所有用户,*作为一项通用政策*。这一点对于可能将 Rust 代码作为 API 主要用户的模块来说尤为重要。

我承认,我不知道维护者不忽略Rust代码在实践中意味着什么,我同意这不应该意味着C语言维护者对Rust绑定进行代码审查,或对整个Rust模块拥有否决权,或维护者审查Rust模块的架构或设计,或加入Rust模块邮件列表。但是,C语言的维护者不应该对Rust如何使用API不闻不问,更不应该假装Rust不存在。

>因此,如果有人想用 Rust 编写软件,但只使用 DMA 驱动程序,那应该没问题。

这部分是合理的。我有反驳过吗?

-- macspoofing

我有反驳过吗?

你没有,但克里斯托夫-赫尔维格(Christoph Hellwig)说了,这就是上周整个争论的起因。

-- tremon

我认为这里有一个根本性的脱节,我不确定我是否完全理解。

在我看来,你似乎是在谈论一种假设情况,即 Rust 需要一些其他语言不需要的接口。而你却说不出那可能是什么,因为你想不出那会是什么样子的例子。而且,在这种情况下,Rust 是这个驱动界面的主要用户。

但如果是这样,那就真的接近于 “如果事情不同,它们就会不同 ”了。如果不是这样,那我就不明白你的意思了。

界面没有任何问题。Rust 可以很好地使用它。它不会做任何 C 代码不会做的事。在我看来,他们甚至没有要求任何东西。维护 DMA 驱动程序的人并不希望 Rust_使用他的接口,他拒绝的是 Rust 代码与他的驱动程序接口的 PR。

我能想到的最接近的比喻是,他写了一本书,但他不想让左撇子读这本书。

应用程序接口维护者应该只关心应用程序接口是如何被使用的,只要它是可使用的,并且不会导致意想不到的副作用。而这两点都不应受到使用 API 的语言的影响。

-- bena

> 如果有人想使用 usb 驱动程序与硬币电机连接,以制造振动内衣

在安装 CMake 的同时开始撰写商业计划书

-- renewedrebecca

以前的讨论 https://news.ycombinator.com/item?id=43123104

-- homarp

我有一种感觉,无论 Linus 走得多慢,这都会导致分裂。如果 Linus 最终推行 Rust,守旧派就会分叉到纯 C 语言版本,那就不好了。

-- SeanLuke

似乎不太可能。请注意,Hellwig 是仅存的主要独立 Linux 内核开发者。其他开发者的工资都是由 Linux 基金会、红帽、谷歌等支付的。他们不太可能采取威胁到自己薪水的行动。

而且赫尔维格是以承包商的身份工作的,他不是像康-科利瓦斯那样的志愿者。赫尔维格也不是真正的独立人士。

-- bryanlarsen

这对内核编译时间和工具链要求意味着什么?

-- 1vuio0pswjnm7

没什么新意,内核已经在相同的部分使用了 rust

-- vdfs

[已删除]

-- jvillasante

谁来接棒?

-- cosmicradiance

怎么接?

-- knowknow

[删除]

-- perching_aix

为了什么?

-- tmountain

显然是为了 [标记]。

-- perching_aix

用于在 Windows 上运行的世界服务器和超级计算机….。/s

-- fransje26

我们也可以把它们的电源关掉,现在还来得及:)

-- perching_aix

[删除]

-- lrsa1218

这里没有任何模棱两可之处,Torvalds 只是在执行常识: Rust 开发人员不能是神婆,而 C 开发人员不能是破坏者。

如果说有什么不妥的话,那么整场风波就是内核开发人员缺乏常识和友情的表现,令人震惊。独裁者不应该强制执行显而易见的事实,但在这种情况下,独裁者似乎就是这样做的。

-- ykonstant

这怎么会是一种模棱两可的立场?“子系统维护者不一定要允许使用 Rust,但其他子系统可以并将为你的代码构建自己的绑定”,这似乎相当明确。

-- i80and

后来的跟进更让这一观点不再模棱两可

https://lore.kernel.org/rust-for-linux/2cbxfvvsau5sobm3zo5ds…

-- dralley

你不满意莱纳斯的领导能力,是因为他做出了你希望他做出的决定吗?

-- blueflow

愿意为不了解情况的人详细说明一下吗?

-- bayindirh

>我们已经把我们的开发模式变成了一个运转良好的工程奇迹

尤其是那些邮件列表,的确是工程奇迹!

-- high_na_euv

这有什么错?

-- timeon

莱纳斯说,非铁锈色 C 程序员不能否决铁锈色代码,但他没有明确说明如何反其道而行之。是 C 语言方面的 rustacean 提议的修改导致了这场闹剧。我看不出这里有什么进展。

-- evanjrowley

我认为这不准确。Rust 驱动程序之间共享的 Rust DMA 代码才是导火索。C 代码没有变化。

-- Diggsey

这些补丁完全没有触及 C 语言部分,这一点莱纳斯在斥责时也说得很清楚。

-- dralley

> 正是 Rustacean 提出的 C 语言修改导致了这场闹剧。

你为什么要这么说?

从这篇文章所依据的电子邮件 [0] 中可以看出:

> 事实上,你反对的拉取请求完全没有触及 DMA 层。

> 事实上,你反对的拉取请求完全没有触及 DMA 层,它只是它的另一个用户,在一个完全独立的子目录中,并没有以任何方式改变你维护的代码。

[0]: https://lkml.org/lkml/2025/2/20/2066

-- timeon

对于 Rust 的用户来说,我认为只有一条可行的道路: 分叉内核,做任何需要的修改。这已经不是 Linux 了,但多年前 Linux 就是这样从 Unix 起步的。

-- glitchc

不,Linux 不是这么开始的。如果你想比较的话,那就是没有从 Unix 分支出来。Linux 一开始是一个完全独立的项目,是一个打印 AAA…BBB 的多任务内核,随着它的发展,基本上与 Unix 兼容。但它并不是任何东西的分叉。

-- Tor3

是的,我的评论措辞不当,但精神是正确的。Linux 不可能来自 Unix,因为当时的 Unix 操作系统是闭源的。它不是一个分叉。然而,Linux 从一开始就打算成为 Unix 的开源变体。托瓦尔兹从一开始就把兼容 POSIX 和 ABI 作为目标,这也是他开发内核的既定目标之一。

-- glitchc

我认为这不可行。要做到这一点,你必须与内核保持多年的合作关系,可能需要十年以上的时间,才能达到某种临界质量,并变得足够有影响力,能够脱离内核,推动与内核背道而驰的决策。这还不算让这些有能力的团队(内核的铁锈支持者、经验丰富的维护者和贡献者,他们都不想与内核扯上任何关系)在最好的情况下并行工作,在最坏的情况下部分对立,而他们本可以一起工作,这将是多么大的损失。

-- zaep

为什么不呢?Linux 就是这么开始的。当时没有一个 Unix 版本是免费的。当时是谁付钱给社区的?

如果有足够多的人支持 Rust 操作系统,它就能超越 Linux。我想,人们再也不会有远大的梦想了。

-- glitchc

> 要想实现这个目标,你就得在内核上跟上好几年,甚至十几年。

这是好事。这将考验 rust 的可靠性。

-- beretguy

这与其说是技术问题,不如说是人力和资金问题。当然,可以 fork Linux 并用 Rust 重写。但如果没有 Linux 基金会的资金和专业知识,谁会花那么多时间和精力去做这件事呢?你很可能在几年内就会精疲力竭,无法对代码库进行实质性的转换。

-- wsve

他们可以打破常规,拒绝支持超过一定年限的硬件。或者只专注于 Mac 等特定平台。

-- glitchc

为什么你认为 “不是用锈编写的 ”是 Linux 内核的根本特征?

-- thfuran

Rust 社区试图做的事情与整个自由软件运动背道而驰。他们想把一种新语言强加给现有的维护者,而这些维护者改变的动力有限。

自由软件中的 “自由 ”不仅是啤酒的自由,也是自由的自由。这一点被遗忘了。人们开发自由软件是因为他们想开发,而不是因为他们不得不开发。如果开发者不想使用 Rust,可以也不应该强迫他们使用。不管 Rust 客观上是否更安全、更好,或者任何所谓的理由。强迫使用会消除选择的自由。

Rust 开发者应该开发自己的内核和操作系统。让它直接与 Linux 竞争。在开源领域,这才是王道。

-- glitchc

自从康-科利瓦斯(Con Kolivas)于 2007 年辞职后,就再也没有志愿者为 Linux 内核做出重大贡献了。每个人都把它当作一份工作来做。因此,他们不得不这么做,前提是他们还想继续拿工资。

-- bryanlarsen

> 他们想把一种新语言强加给现有的维护者群体

“Rust 人 “是现有维护者群体的一部分,而不是外部力量。

-- steveklabnik

你所说的与自由软件毫无关系。

首先,“自由 ”并不意味着不受 Rust 的约束。

-- imtringued

兄弟是在一个关于 C 和 Rust 之间的固定解决方案的主题中回答这个问题的吧,至少在评论之前先了解一下这个主题吧

-- Vilian

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

你也许感兴趣的: