三大操作系统入场,谁能掌控 Rust 的未来?
三大操作系统入场,谁能掌控 Rust 的未来?
Rust编程语言以其卓越的内存安全特性,在操作系统领域展现出强大的发展潜力。Linux、Windows和Android三大操作系统纷纷拥抱Rust,但其在Linux内核中的应用却进展缓慢。本文深入分析了Rust在操作系统领域的应用现状、面临的挑战以及未来的发展前景。
2019年2月,在BlueHat以色列安全会议上,微软安全工程师Matt Miller的一篇报告《Trends, challenges, and strategic shifts in the software vulnerability mitigation landscape》引起了业内的广泛关注。他提到,在过去12年里,微软每年发布的补丁中约有70%都是针对内存安全漏洞的修补。
这都是因为Windows主要用C和C++编写。它们都是“内存不安全”的编程语言,提供了直接访问内存的能力。这种能力虽然强大,但同时也增加了安全风险,因为开发人员在编写代码时一不小心,就可能制造出能够被利用的安全漏洞。正如Matt Miller所指出的,大多数漏洞正是开发人员在编写C和C++代码时,无意中引入了会导致内存损坏的错误而造成的。
解决这个难题的方式就是,从C/C++编程语言转向所谓的“内存安全语言”。这类语言,从设计之初就内置了针对内存损坏漏洞的防护措施,包括预防缓冲区溢出、竞争条件、内存泄漏、使用后释放以及与内存指针相关的错误。
而Rust,被微软视为C/C++的最佳替代品。Linux内核面临的问题也一样,因为其主要编程语言也是C语言。
事实上,除了Rust之外,还有C#、F#、.NET、Swift、Go和Python等多个被公认的内存安全语言,并且被广泛使用。但真要认真比较起来,Rust在某些方面还是要更胜一筹。比如C#虽然也属于内存安全的语言,但不如Rust在系统编程领域的内存安全模型那样先进;Go某些功能缺失,影响编写高可靠性代码,而且在多个线程的情况下,其内存安全存疑。
总而言之,能够实现内存安全性还兼具C/C++的高性能和高并发的,只有Rust。
Rust与C/C++一样,具有最小且可选的“运行时”。Rust的标准库(stdlib)非常小,依赖于libc。这意味着,Rust可以在没有完整操作系统支持的环境中运行,例如嵌入式系统或裸机编程。此外,Rust编译为原生机器代码,性能接近C/C++,且编译器优化能产出高效代码,与手动优化过的C和C++代码相媲美。
因此,当从代码执行的速度、开发者对程序行为的控制能力以及程序性能的可预测性这三个方面来看,Rust的性能表现与C和C++相似。
这并不意外,Rust本来就是为替代C及C++而诞生的。创始人Graydon Hoare创造Rust的灵感,就是来源于电梯故障——电梯等设备内部的软件通常都是用C或C++编写的,好处在于运行速度快,但也很容易意外引入内存错误,造成程序崩溃。
Graydon Hoare曾直言,Rust的目标用户,就是“对C++感到沮丧的开发者”——包括他自己。
So if you are in a similar situation we're in, repeatedly finding yourself forced to pick C++ for systems-level work due to its performance and deployment characteristics, but would like something safer and less painful, we hope we can provide that.
如果你和我们处于类似的情况,发现自己不得不因为性能和部署特性而反复选择C++进行系统级工作,但又希望有更安全、痛苦更少的选择,我们希望我们能为你提供这样的解决方案。
因此,要论谁是最适合操作系统的编程语言,Rust当之无愧。
与C/C++相比,Rust确实是一个较新的编程语言,资历尚浅。Rust首次发布是在2010年,而C语言最早可以追溯到1972年,C++则是在1983年。
也正是因为出现得晚,众多编程语言的优缺点才能充分展现出来,这使得Rust的创造者Graydon Hoare能够在前人基础上,将这许多优点集于一体,从而创造出了Rust。
一个实验性项目:Rust for Linux
四年前,一个致力于将Rust语言引入Linux内核的项目——Rust for Linux(RFL)启动了。这一项目获得了微软和谷歌等行业巨头的支持,甚至连Linux创始人Linus Torvalds也认为其值得一试。他们分别代表了三大操作系统:Windows、Android,以及Linux。
这是一个实验性质的项目,起初,各方都是抱着谨慎试水的心态。
微软率先在2019年展开行动,开始尝试使用Rust重写原本用C和C++编写的Hyper-V驱动程序,希望减少Windows中的内存安全漏洞。这一行动标志着,对Rust语言在操作系统级别应用的探索开始了。
谷歌在2021年4月开始在Linux内核中推动使用Rust。不过,其目标并不是用Rust替换内核中的C代码。“Linux内核有超过3000万行代码,因此我们的目标自然不是将其全部转换为Rust,而是允许用Rust编写新代码。”
Linus也是抱着观望的态度。
我们拭目以待。我不认为Rust会接管核心内核,但在其中开发单个驱动程序(甚至可能是整个驱动程序子系统)听起来并非完全不可能。也许文件系统也是如此。因此,这并不是“取代C”,而是“在有意义的地方增强我们的C代码”。
当然,驱动程序大约占实际内核代码的一半,因此有很大的空间。但我不认为有人真的期望用Rust全面重写现有的驱动程序,更多的是“有些人会用Rust做新的驱动程序,并且一些驱动程序可能会在有意义的地方被重写”。
据Linus透露,这几年里,大部分时间都在建立Rust基础设施——支持Rust代码在内核中运行和集成的工具、库、以及必要的抽象层。
我们在去年合并了Rust初始基础设施,它一直在不断增长,但是内核还没有真正依赖它的部分。
目前Rust并没有真正释放出它的能力,但是我认为明年(2024)我们实际上会开始会积极使用Rust来集成驱动程序甚至一些主要的子系统(Major Subsystems),所以这需要数年时间的积累才能让Rust成为内核的重要组成部分,Rust肯定会成为其中之一。
由于在Linux内核中尚未明显看到Rust的成效,这项工作遭到了反对者的质疑,被贬低为“玩具项目”,用Rust开发内核,不过在浪费时间而已。
项目遭遇的阻力颇多,进展缓慢。Linus也一改此前对Rust试探的态度,而是变得更加急切,在今年8月在香港举行的CubeCon大会上表达了他的失望。
Linux内核中的Rust采用速度太慢了,我原以为更新会更快一些,但部分问题在于,资深内核开发者习惯了使用C语言,并不熟悉Rust。他们对于不得不学习一门在某些方面差异很大的新语言,并没有太大的热情。因此,对于Rust的使用,确实存在一些抵触情绪。
RFL受阻,跟Rust关系不大
与RFL的境况不一样的是,微软和谷歌在引入Rust这件事上尝到甜头后,要更加激进。不仅向Rust基金会捐赠100万美元表示支持,连自家的操作系统也在加速拥抱Rust。
微软在Windows 11中推出基于Rust的内核实现,其中包括可以创建矩形、多边形和椭圆的GDI Regions功能。
在去年的BlueHat IL 2023会议上,微软操作系统安全副总裁David Weston曾透露,内核已经增加了3.6万行代码,在测试环境下没有出现重大的性能退步,Win32k的GDI(图形驱动接口)移植到Rust后,在Windows上启动时能够通过所有测试。
今年初,微软Azure寻求Rust开发人员重写核心C#代码。微软Azure首席技术官Mark Russinovich此前就曾宣布,新软件项目应该使用Rust,而不是C/C++。
至于谷歌,早已在Android和其他产品中广泛使用Rust编程语言,并且正在尝试脱离C/C++,将新代码的开发转移到内存安全的语言。
在Android 13中,大约21%的新原生代码(C/C++/Rust)都是用Rust编写的。AOSP中的新功能和组件(例如Keystore2、新的超宽带(UWB)堆栈、DNS-over-HTTP3、Android的虚拟化框架(AVF)以及各种其他组件及其开源依赖项)中总共约有150万行Rust代码。这些是需要系统语言的低级组件,否则这些语言将用C++实现。
在Android 12中,Android平台支持Rust编程语言,作为C/C++的内存安全替代方案。从那时起,谷歌一直在Android开源项目(AOSP)中扩大我们的Rust体验和使用范围。
再回过头来看Linux,似乎已经落后了不少。经过四年的努力,第一个用Rust编写的网络PHY驱动程序,才终于在今年3月初的v6.8版本中首次被纳入Linux主线。
要在一个稳定运转了30多年的Linux内核中引入一门新语言,这并不容易。在一个靠爱发电的开源社区,你不能强求他人去学习、使用一门新的语言,更何况Rust语言以学习曲线陡峭著称。
Linux面临的,也不是单纯的技术问题,而是在一个较为稳定的内核维护者团队引入大量的新鲜血液。这是新团队与旧团队,新文化与旧文化之间的冲突。
这种冲突无疑会动摇开发者的信念。最近,由于内核维护者群体中反对声音过多,RFL的核心开发者、微软工程师Wedson Almeida Filho宣布退出该项目的维护者团队。
之所以决定退出项目,是因为在过去四年的工作当中,我发现自己的精力和热情已经被严重消磨,越来越抗拒回应那些跟技术无关的废话。所以这份任务,最好是留给那些仍然抱有这份热情的成员。
原本项目的代码审查进度就很慢,维护者的退出无疑会进一步拖慢项目进展。根据北京邮电大学李弘宇等人的研究,RFL的瓶颈主要体现在代码审查环节,而非代码开发本身。
代码审查(PR,即Pull Request)的速度随着时间的推移显著变慢,例如,2023年1月至2023年7月之间的PR平均需要280小时才能审查,是3年前的200倍。这表明生成RFL代码的速度比使用(即审查并最终将RFL代码合并到上游内核中)的速度快得多。
如果这些冲突无法解决,随着内核开维护者年龄逐渐变大,因Rust集成到内核吸引的年轻开发者又迟迟无法融入社区,Wedson Almeida Filho对于Linux将被取代的担忧或许很快就会到来。
我坚信内核开发的未来在于内存安全语言。我不是那种很有前瞻性的人,但如果Linux没法把这项优势内化己用,我担心其他内核终将像取代Unix那样冲击Linux。
当前已经有使用Rust编写的类Unix操作系统——Redox,它被看作是Linux和BSD的潜在替代品。尽管该项目的规模还不足为惧,但其一直在找机会补位。
Rust与操作系统,谁决定谁的未来?
Rust语言在众多项目中取得了成功,如Mozilla的浏览器采用Rust编写CSS引擎,亚马逊的云服务如Amazon S3、Amazon EC2等也完全基于Rust构建,甚至连Discord的客户端和服务器端、Figma的多人服务器都选择了Rust进行重写。
然而,在开源操作系统领域,Rust的发展速度始终显得缓慢。为了改变这一现状,Rust团队也正在努力推动其在操作系统领域的发展。
不久前,Rust团队公布了2024年下半年的26个项目目标,其中3个被指定为flagship目标,代表预计将产生最广泛整体影响的目标。这些目标包括发布2024版本、提升异步Rust编程体验,以及推动Rust for Linux项目。
Rust for Linux项目标志着Linux内核对Rust开发的实验性支持,这被认为是Rust的一个分水岭,表明Rust确实有能力开发各种低级系统应用。但目前相关支持工作还停留在实验性阶段,项目团队计划在2024年下半年努力扫清障碍,以便更好地融入Linux内核。
与此同时,FreeBSD社区也在讨论是否将Rust语言纳入基础系统(base system),以改善系统的安全性和可维护性。尽管经历了两次讨论,但都没有最终的结论。FreeBSD核心团队成员Warner Losh表示,FreeBSD社区需要一些明显的成功案例才能考虑将Rust纳入基础系统。他指出,Rust在LLVM中没有得到很好的开箱即用支持,这带来了许多后勤问题。
不过,Rust在操作系统领域不可替代性,已经在谷歌这里有了验证。迄今为止,Android的Rust代码中尚未发现任何内存安全漏洞。谷歌甚至宣称,它是解决内存安全问题的最强大的工具之一。
我们并不指望这个数字永远保持为零,但考虑到两个Android版本中新Rust代码的数量,以及使用它的安全敏感组件,这是一个重大的成果。这表明Rust正在实现其预期目标,即阻止Android最常见的漏洞源。在Android的许多C/C++组件(例如媒体、蓝牙、NFC等)中,历史漏洞密度大于1/kLOC(每千行代码1个漏洞)。根据这一历史漏洞密度,使用Rust很可能已经阻止了数百个漏洞进入生产环境。
因此,可能不是操作系统决定了Rust的未来,而是Rust在左右这些项目的未来。
为了脱离C/C++,推动Rust语言在Android中的应用以提高安全性、稳定性和质量,谷歌正在行动:在Android平台上增加Rust的使用,实现用户空间硬件抽象层(HAL)的Rust版本,在受信任的应用程序中支持Rust,将Android虚拟化框架中的虚拟机(VM)固件迁移至Rust编写,等等。
我们已经可以预见,在未来操作系统开发中,Rust凭借内存安全特性和高性能,将成为关键语言之一。Rust的帝国,才刚开始。
**那么,在操作系统之外,Rust也将取代C/C++吗?**有人就认为,Rust适合写内核级别的代码,但并不是适合业务开发,因为它不够高效,不够灵活。