5

Asahi Lina讲述了使用Rust编写Linux驱动程序的经验

 1 year ago
source link: https://www.jdon.com/62764
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Asahi Lina讲述了使用Rust编写Linux驱动程序的经验


关于内核中的Rust是否有用,有很多奇怪的争论......根据我的经验,它比我想象的要有用得多!"。
在我的驱动程序上只调试了大约两天,我就从第一次渲染变成了一个可以运行游戏、浏览器等的稳定桌面。

所有的并发性错误都在Rust中消失了!内存在需要释放的时候就会被释放!
一旦你学会让Rust和你一起工作,我觉得它就会引导你写出正确的代码,甚至超越语言的安全承诺。它真的很有魔力!

如果我用C语言写这篇文章,我绝对不可能不遇到锁竞争竞态条件、UAF、内存泄漏和各种各样的坏问题。
在Rust中只是一些逻辑错误和一些核心内存管理问题。
一旦这些被修复,驱动程序其余部分就会工作!!

我试了一下kmscube,它顺利地渲染帧。然后我试着启动一个KDE会话,过了一会儿它就崩溃了,而你知道什么原因没有导致它?3个进程试图同时使用GPU,并行分配和提交命令,是并行!!

在这样一个复杂的驱动中,当事情在单线程中运行后,所有的锁定和线程都神奇地按计划运行,没有奇怪的锁竞争或事情互相踩踏,就我而言,对于一个如此复杂的驱动来说,这是完全闻所未闻的。

然后所有的内存管理……就像魔术一样发生。使用 GPU 的进程退出,它使用的所有内存和结构都被释放。我的日志中有几十行都被正确释放了。我没有写任何胶水,Rust 为我做了这一切!
(我写了将 DRM 子系统连接到 Rust 的部分,包括在文件关闭时删除一个File结构,这就是触发所有内存管理的原因......剩下的部分由Rust完成!)

我实际上花了更多的时间来追踪一个被遗忘*的 DCP 驱动程序(由Alyssa和Janne用C语言编写,已经过测试),它导致堆溢出,在上面花费的时间比我花在Rust中追踪我的全新驱动的CPU端安全问题(unsafe 代码)的时间还要多。

甚至像正确处理ERESTARTSYS这样的事情。Linux Rust鼓励你在任何地方使用Result<T>(Err 是 errno 的内核变体),然后你只需在你睡眠/等待sleeping/waiting条件的地方后面加一个?(就像编译器告诉你的那样),它就能正常工作了。

说真的,C和Rust在这里有很大的区别。
Rust的炒作是真实的!无畏的并发性是真实的!
虽然有一些unsafe {} 块并不能掩盖否定Rust的优势!

Asahi Lina补充:
从真正的驱动程序的第一次渲染到稳定的驱动程序,需要两天时间。当我拿到第一张渲染图的时候,几乎所有的驱动程序都已经写好了!"。

我真正想说的是,我花了两天时间来修复错误,使事情能够正常和稳定地进行,而如果驱动是用C语言编写的,我还必须处理并发和内存安全问题,那就会花更多的时间。
请记住,这是内核方面的驱动程序,它的工作只是管理内存和向GPU提交请求。
要达到这个目的有很多复杂的因素,但是一旦你达到了这个目的,从内核的角度来看,不同的应用在使用GPU的方式上几乎没有任何差异。所有OpenGL的东西都是在用户空间处理的,Alyssa在这方面已经工作了很长时间(在macOS下测试)。因此,最终,对于这种驱动,在你获得了渲染和(相对较少的)功能/用例支持之后,剩下的大部分工作就是使其稳定并修复安全和并发错误。而......在Rust中并没有多少这样的东西!"。

以下是这两天的大致情况:

  • 移除mesa中的一些旧的黑客,这些黑客会破坏事情。
  • 修复mesa中的kmsro/buffer导入问题
  • 实现PRIME缓冲区共享工作所缺少的东西
  • 重写我的DRM抽象,因为我误解了C语言的API,导致它不能和PRIME一起工作。
  • 重构了一些驱动代码,因为它也破坏了驱动内部的PRIME缓冲区共享,这也是因为我误解了它应该如何工作。
  • 弄清楚如何修复固件端的TLB无效性。
  • 为GPU端TLB不能正常失效而导致的内存损坏问题伤透脑筋,然后想出了一个愚蠢的解决方法,即每次渲染后等待GPU关闭。

因此,实际上,大部分工作是使缓冲区共享工作,这对于让多个图形应用程序相互发送帧是必要的,然后与TLB失效问题作斗争(这在硬件层面上导致内存安全问题,所以这不是Rust可以帮助解决的问题--这场战斗仍在进行,我现在有的只是一个解决它的黑客)。

在最后一个解决方法之后,一切都开始稳定地工作,所以事实证明,所有明显的剩余内存安全问题的根源实际上是GPU TLB,而驱动本身实际上是非常可靠的。这就是令人惊奇的部分!

Reddit网友:
1、我是一名长期的 C 开发人员,C++ 开发人员已经有几年了,现在已经使用 Rust 作为我的主要语言 3 年了。
我发现 Rust 是最容易阅读的语言。跳入 Rust 核心或其他项目的某些部分并快速开始理解代码流是多么容易,这让我感到非常惊讶。

2、阅读 Rust 代码时,这种语言使得隐藏棘手的错误变得非常困难(显然并非不可能,但惯用代码通常非常简单)。
阅读 C 语言时,您需要时刻注意一切,因为该语言不允许抽象。您需要了解指针可能变为无效的每个位置,您需要手动跟踪资源所有权,以确保它们在正确的时间释放,您需要了解给定函数可能调用未定义行为的每种情况,以及有时,规则可能会根据您所针对的平台或正在使用的编译器版本而改变。内核代码也不是严格的标准 C,而是使用 GCC 扩展,这是您需要注意的更多内容。
C++ 允许抽象,但也伴随着糟糕的设计决策、不能很好地协同工作的特性以及许多未定义行为的实例。
Rust 只是一种较新的语言,其高级功能从一开始就被设计为难以滥用,并且安全性是一等公民。

3、Rust 是迄今为止最容易审查的代码,甚至比 Python 更容易。您可以非常准确地了解某些代码的运行时行为,而无需调查可能采用的路径的实现。在哪里存在潜在问题,您总是知道它们可能源自哪里,因为它们需要显式的函数调用或 unsafe块。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK