写点什么

Rust 重写万行 C,太有必要了!

作者:高端章鱼哥
  • 2023-07-06
    福建
  • 本文字数:2370 字

    阅读完需:约 8 分钟

在过去的一段时间里,“用 Rust 重写”的潮流席卷了整个开发领域。作一颗正在冉冉升起的新星,Rust 不仅承诺了更好的内存安全保障、更高的技术稳定性,还能够兼顾开发与执行效率。这也让越来越多的系统开发者开始转向这门面向未来的编程语言。


这不,就在最近,又一款知名开源项目 Ockam 放弃了系统内数万行的 C 语言代码,并最终用 Rust 实现了对整个项目的重写。在完成这项庞大的工程后,Ockam 的创始人 Mrinal Wadhwa 也在一篇博客中分享了自己带领团队从 C 转向 Rust 的心路历程。


1、C 语言:迷人的陷阱

作为一款开源开发者工具,Ockam 在 GitHub 上拥有 3.3k Stars,其核心功能是帮助用户构建可信的动态数据,为用户的应用添加端到端的加密和认证通信;保障应用能够获得端到端的数据完整性、真实性和机密性。


研发团队希望 Ockam 能够在任何环境中运行,包括受约束的边缘设备或是强大的云服务器。除此之外,Ockam 的另一个目标则是可以在任何类型的应用程序中使用,无论应用程序使用什么语言构建。


这样的诉求使得 C 语言成为了一个构建 Ockam 项目的明显候选者——它能够被绝大多数设备编译,并且所有流行语言都可以通过某种形式的接口调用 C 库。在这样的情况下,Ockam 能够为所有其他语言提供惯用的包装器。


团队的想法是将以通信为中心的协议核心从硬件行为中分离,并为想要支持的硬件提供可插拔的适配器。在这样的思路下,研发人员在最初的版本中将项目的 Ockam 的核心实现为了一个 C 库,并用其他语言包装器对库进行了包装。

2、一触即溃的安全问题

然而基于 Ockam 核心所实现的 C 库虽然满足了项目四处运行的需求,但由于 C 语言内存管理的薄弱,团队所实现的 C 库中许多与加密相关的代码容易存在漏洞,一个微小的失误就会导致系统变得不安全。


这与 Ockam 项目的目标简直背道而驰,为了将这些问题隐藏起来,并提供易于正确使用的开发者界面。团队开始尝试使用 C 语言构建安全简单的接口。但在多次迭代中,开发人员渐渐发现自己不得不掌握大量关于协议状态和状态转换的细节,并且即便非常小心,代码中也总会出现难以察觉的漏洞。

3、Elixir:并不够好的继任者

面对无比痛苦的迭代工作,始终无法解决内存安全问题的 Ockam 决定放弃 C 语言,并为项目寻找更适合的继任者——彼时的他们将视线投到了以 Erlang 为基础的 Elixir 语言之上。


Elixir 程序运行在 Erlang 虚拟机 BEAM 上,BEAM 提供了 Erlang 过程。Erlang 流程是轻量级有状态并发参与者。由于 actors 可以在维护内部状态的同时并发运行,所以运行一个并发的有状态协议堆栈 Ockam 传输+Ockam 路由+Ockam 安全通道非常容易。



但令人遗憾的是,Elixir 天然为支持高负载项目而生,无法像 C 语言一样在小型或受限的计算机上拥有良好的运行表现,此外生态并不够成熟的 Elixir 也无法成为某些特定语言管理包装器的良好选择。

4、Rust:令人兴奋的探索之旅

在经历了接二连三的失败后,Ockam 团队意识到他们的需求核心是在保障安全性的前提下实现轻量级的 actors,但无论是 C 语言还是 Elixir 都无法做到完美适配。从这时起,Wadhwa 开始带领团队研究 Rust,并很快发现了这门语言独特的魅力。


与 C 语言调用约定(calling convention)的兼容


Rust 库能够导出与 C 调用约定兼容的接口。这意味着任何静态/动态链接或调用 C 库中函数的语言都能够以完全相同的方式调用 Rust 库中的函数。并且由于大多数语言都支持 C 中的原生函数,所以他们也支持 Rust 中的原生函数,从包装器的角度来看,Rust 和 C 几乎没有任何区别。

支持多目标


Rust 使用 LLVM 编译,这意味着它可以针对非常多的计算机。这个集合不像 C 用 GCC 和专用的 GCC 分支所能达到的那样大,但仍然是一个非常大的子集。随着新的 LLVM 目标和 Rust 中潜在的 GCC 支持的增长,这能够满足 Ockam 到处运行的需求。

强大的内存安全性

Rust 的内存安全功能消除了释放后使用、双重释放、溢出、越界访问等许多常见错误的可能性。根据此前的调查,这些错误会导致 C 或 C++库中 60-70%的严重漏洞。Rust 在编译时提供了这种安全性,使其在编写需要高性能、受限环境中运行并高度安全的代码时具有很大的优势。

Async/await

让研发团队坚信 Rust 与 Ockam 能成为天作之和的最后一个原因是 Rust 中的 async/await。Ockam 需要轻量级的 actors 来创建简单而安全的协议栈接口。async/await 意味着在 tokio 和 async-std 这样的项目中已经完成了大量创建 actor 的工作,团队能够很轻松地在此基础上构建 Ockam 的 actor 实现。

5、最终的天作之合

基于 Rust 的 async/await 无论在大型计算机还是微型计算机上运行,都可以向用户呈现完全相同的界面。位于 Ockam Workers 上的协议接口也可以在任何不同地方运行的情况下呈现完全相同的简单接口。


最终,在 Wadhwa 的带领下,Ockam 放弃了系统内的数万行 C 语言代码,并利用一段时间完成了向 Rust 的全面转型。在经历了重写后的多次稳定性迭代后,如今任何用户都能够使用重获新生的 Ockam 包,在任何设备上利用简单函数调用创建他们想要的端到端的加密和相互认证的安全通道。


更重要的是,依托于 Rust 的内存安全优势,这个函数调用的背后能够隐藏所有潜在的复杂性和漏洞风险。

6、值得期待的未来

在 Rust 日渐趋于宏大的叙事中,Ockam 的故事其实只是一个缩影。对如今绝大多数受困与内存安全问题的项目而言,使用 Rust 或基于 Rust 进行重构已不再是一项实验或赌注,而是切实可行且足够可靠的解决方案。


在 Ockam 之前,微软已于 4 月宣布,出于对内存安全的考虑,将使用 18 万行 Rust 代码重写核心 Windows 库;Python Web 框架 Flask 的作者 Armin 也在 Python 2023 发展趋势的文章中提出了将 Rust 融入 Python 项目和工具的想法;Ruff 创始人在成立新公司时,同样宣称了要在未来通过 Rust 彻底改变 Python 生态。


更值得欣喜的是,Rust 的进化如今仍在继续,根据其发布的 Rust 2024 路线中显示,官方团队将在未来继续在降低学习门槛、壮大生态连接等方面努力,帮助 Rust 尽快撕下被人诟病的“曲高和寡”的标签,让其尽快在更多场景中发挥价值。对此,Rust 的未来,的确值得我们每个人的期待。

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Rust重写万行C,太有必要了!_rust_高端章鱼哥_InfoQ写作社区