Android作为一个完整的操作系统解决方案,涉及到很多移动的部件。总的来说,这些部分先是应用生态系统,然后才是操作系统本身。
作为一个开发者,你选择的编程语言,根据你正在开发的Android的哪一部分而有所不同。对于应用开发者来说,Java和Kotlin是当下流行的选择。对于从事操作系统及其内部底层部分的开发者来说,C和C++是迄今为止一直热门选择。
今天,谷歌为Android操作系统开发者增加了第三个选择——Rust,现在Android开源项目支持Rust编程语言来开发操作系统本身。
C和C++的局限性
Android操作系统的底层部分需要C和C++等系统级编程语言构架。这些语言为开发者提供了控制和可预测性,这些在访问低级系统资源和硬件时非常重要。
但却带来了一个缺点,C和C++不能提供内存安全保证,使得容易出现错误和安全漏洞。而且开发者有责任在使用这些语言时管理内存寿命,但在复杂和多线程的代码库中,这种想法做起来比说起来难太多。
现在,C和C++共同构成了Android平台上数以千万计的代码行,这些内存安全漏洞成为最难解决的代码错误来源,占Android高危安全漏洞的70%左右。想要从修复Bug的角度处理问题已经变得不现实,更好的办法还是从一开始就预防这些Bug。
缺乏内存安全性保证迫使开发人员在严格受限和无特权的沙箱中运行Android进程,但沙盒在资源上的成本很高,不仅消耗额外的开销,还引入延迟。沙盒也不能完全消除代码的漏洞,而且由于Bug密度高,沙盒的功效会降低,进一步让攻击者连锁多个漏洞。
另一个限制不是C和C++独有的,但适用于所有的内存安全问题,那就是错误状态必须在工具化的代码中实际触发,才能被检测到。所以即使你的代码有很好的测试,实际的Bug也可能一直没有被发现。但当你发现Bug时,让它们得到修复又是一个漫长且昂贵的过程,而且不一定能得到修复。因此,Bug检测变得不可靠,鉴于这些局限性,Bug预防才是更好的方法。
这就是改用Rust这样的内存安全语言的原因。
Rust的好处
Rust通过使用编译时检查和运行时检查相结合的方式提供内存安全保证,以强制执行对象的寿命/所有权,并确保内存访问是有效的。在实现这种安全性的同时,还能提供与C和C++相当的性能。Rust还减少了对沙盒的需求,让开发人员有更多的开销空间来引入更安全、更轻量的新功能。
虽然Rust确实有它的好处,但一夜之间将整个Android操作系统换成Rust也是不现实的,而且也根本不需要这样做,因为大多数Android的内存错误都发生在新的或最近修改的代码中,甚至有大约50%的代码是一年内写的。因为谷歌认为,其内存安全语言的工作最好集中在新的开发上,而不是重写成熟的C和C++代码。
Rust一个重要优势是它专注于防止出现Bug,而不是严重依赖于检测Bug,从最开始就提高代码的正确性。它还有几个关键特性,如内存安全、数据并发、更有表现力的类型系统、默认的不可变引用和变量、更安全的整数处理、标准库中更好的错误处理等。
切换到Rust对Android意味着什么?
谷歌表示,在过去的18个月里,它一直在为Android开源项目添加Rust支持。但在Android平台上添加一门新语言是一项巨大的工程。除了需要维护一些工具链和依赖关系外,必须更新测试基础设施和工具,并且需要培训开发人员。
谷歌有一些早期采用者项目,他们将在未来几个月内分享。但即便如此,人们还是明确表示,将Rust支持扩展到更多的操作系统是一个多年的项目。
从目前情况来看,谷歌已经在一些地方使用了Rust。Android新的蓝牙协议栈重写代码 "Gabeldorsche "就是用Rust编写的。Gabeldorsche的工作大约在Android 11的时候就开始了,但目前仍未投入使用。Android的Keystore 2.0模块是用Rust编写的,Android的IPC驱动binder的用户空间部分也是如此。虽然与Android无关,但Fuchsia的新netstack也是用Rust编写的。
对于应用开发者来说,这个切换对你作为应用开发者如何编写应用或框架API来工作没有任何改变。这个切换只影响操作系统的编写方式。据Android开发者关系团队的一位成员透露,谷歌目前也不打算发布Rust NDK。应用开发支持的语言将继续是Kotlin、Java、C和C++。