在 Linux 新版内核中的 Rust 初探,原来是这样的

整理 | 苏宓

出品 | CSDN(ID:CSDNnews)

近来,Rust 爆火。

不久之前,53 岁的 Linus Torvalds 在出席 Linux 基金会主办的 2022 开源峰会时表示,下一个版本的 Linux 内核主线,可能就会合并 Rust 语言提交的 PR 分支。然而,在五天前有开发者询问 Linus 是否在 Linux 6.1 进行补丁合并时错过了一个 Git Pull 请求时,对方称他的电脑内存有问题,合并速度很慢,或将导致 Linux 6.1 补丁合并推迟。

正当众人怀疑他买了一个二手的翻新 ECC 时,10 月 13 日,Linux 内核开发者 Jonathan Corbet 惊喜地分享了一则关于“Linux 6.1 中 Rust 初探”的好消息。接下来,我们将与大家一下看看 Linux 和 Rust 遇到一起,将带来哪些“火花”?

最新进展

根据 Jonathan Corbet 的介绍,在 Linux 6.1 版本中,有很多重要的变化被合并到主线中,而引入对 Rust 的支持也只是其中一个最受关注的方面。虽然 Rust 的到来,为内核开发者的创新带来了一些不同,但是他也发现当前 Linux 内核中的 Rust 还不能做很多有趣的事情。

为 Linux 内核开发 Rust 的工作其实早在几年前就已经开始了,它已经产生了许多支持代码和一些有趣的驱动程序,包括在 Linux 内核中用 Rust 语言编写一个苹果图形驱动。

不过,在最初并入主线内核时,Linus Torvalds 明确表示,应该尽可能少地包含一些功能。因此,这些驱动程序和它们的支持代码被去掉了,必须等待未来的内核发布时候才会被加进来。现在有的只是建立一个可以载入内核的模块所需的支持,以及一个小的示例模块。

构建 Rust 支持

为了让对此感兴趣的开发者更加清楚明白 Linux 内核中 Rust 的支持功能,Jonathan Corbet 分享了开发者可能会遇到的一些问题。

譬如,内核配置过程会在构建系统上寻找先决条件,如果不存在,就会默默地禁用 Rust 选项,这样它们甚至不会显示。

因此,构建 Rust 支持需要特定版本的 Rust 编译器和 bindgen (一个能自动为 C(或 C++)库生成 Rust 绑定的辅助库和命令行工具)工具。具体来说,就是 Rust 1.62.0 和 bindgen 0.56.0 版本。

如果目标系统有更新的版本,配置过程会发出警告,但无论如何还是会继续。对于那些试图用分销商提供的 Rust 工具链进行构建的人来说,更尴尬的是,构建过程还需要 Rust 标准库的源代码,这样它就可以构建自己的核心和 alloc crates 的版本。在分销商开始提供 "Rust for the kernel "包之前,把这些代码放到构建过程可以找到的地方是有点困难的。

获得这种依赖项的方法是放弃分销商的工具链,而从 Rust 存储库中安装所有的东西。其中,Rust 官方的使用指南上详细地描述了 Rust 的上手过程(https://www.rust-lang.org/learn/get-started)。

示例模块

在安装完成后,内核配置系统将设置 CONFIG_RUST 选项,这个选项将可以用于构建示例模块。该模块(samples/rust/rust_minimal.rs)确实很小,但它足以让我们了解 Rust 中的内核代码会是什么样子。首先,写下类似于 #include 的代码行:

use kernel::prelude::*;在 rust/kernel/prelude.rs 中找到声明的拉取,使得一些类型、函数和宏可用。

用 C 语言编写的内核模块包括对 MODULE_DESCRIPTION 和 MODULE_LICENSE 等宏的一些调用,这些宏将有关模块的元数据存放在一个单独的 ELF 部分。module_init 和 module_exit 宏分别标识模块的构造函数和析构函数。Rust 等同于将大部分的模板放在一个宏调用中。

module! { type: RustMinimal, name: b"rust_minimal", author: b"Rust for Linux Contributors", description: b"Rust minimal sample", license: b"GPL", }这个宏对各个字段的顺序很挑剔,如果开发者弄错了就会抱怨。除了把所有这些信息放到一个调用中,“moudule!”宏还包括一个 type: ,它将指向实际模块代码的指针。是实际模块代码的指针。开发者系统可以有一个能做有趣事情的模型,在示例模块中,该类型可以帮助开发者实现愿望。

struct RustMinimal { numbers: Vec<i32>, }

它是一个包含 32 位整数值的 Vec。本身 Rust 允许为结构类型添加接口("trait")实现。因此,这个示例模块为 RustMinimal 类型实现了 kernel::Module trait。 impl kernel::Module for RustMinimal { fn init(_module: &'static ThisModule) -> Result<Self> { pr_info!("Rust minimal sample (init)n"); pr_info!("Am I built-in? {}n", !cfg!(MODULE));

let mut numbers = Vec::new; numbers.try_push(72)?; numbers.try_push(108)?; numbers.try_push(200)?;

Ok(RustMinimal { numbers }) } }这个 init 函数常常被认为是做常规模块初始化的工作。但在这种情况下,被期望做常规的模块初始化工作。在这种情况下,它向系统日志做了一些反馈(在这个过程中,它通过 cfg!()宏,可以在编译时用于查询内核配置参数)。然后,它分配了一个可变的 Vec,并试图将三个数字放入其中。try_push 的使用在这里很重要:一个 Vec 会在必要时调整自己的大小。这涉及到分配内存,这在内核环境中可能会失败。

如果分配失败,try_push 将返回一个失败的状态,这反过来将导致 init 返回失败(这就是代码行最后"?"的作用)。

那么,如果一切顺利,它会返回一个 RustMinimal 结构,其中包含分配的 Vec 和一个成功状态。由于这个模块没有与任何其他内核子系统交互,实际上它不会做任何事情,只是耐心地等待被删除。在 Kernel::Module trait 中没有移除模块的函数;相反,这里使用一个简单的 RustMinimal 类型的析构器。

impl Drop for RustMinimal { fn drop(&mut self) { pr_info!("My numbers are {:?}n", self.numbers); pr_info!("Rust minimal sample (exit)n"); } }这个函数打印出初始化时存储在 Vec 中的数字(从而确认数据在此期间存活)并返回,之后,该模块将被删除,其内存被释放。似乎没有办法让模块删除失败。

最后

在最后,Jonathan Corbet 说道,这就是在 Linux 6.1 中可以对 Rust 内核模块所做的事情的大致范围。这是一个可以玩的东西,但它目前还不能用于任何形式的真正的内核编程。

他表示,“希望这种情况在不久的将来会有所改变。如果幸运的话,Linux 6.2 版内核中的 Rust 将大大增强能力。”

来源:https://lwn.net/SubscriberLink/910762/a26f968ea086e32d/

原文地址:https://www.toutiao.com/article/7154340917548155392/

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


linux常用进程通信方式包括管道(pipe)、有名管道(FIFO)、信号(signal)、消息队列、共享内存、信号量、套接字(socket)。管道用于具有亲缘关系的进程间通信,有名管道的每个管道具有名字,使没有亲缘关系的进程间也可以通信。信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除
Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息。&#xD;&#xA;&#xD;&#xA;按实现原理分,可分为基于计数器和跟踪以及剖析。含义如下:&#xD;&#xA;&#xD;&#xA;计数器:内核维护的统计数据,通常为无符号整型,用于对发生的事件计数,比如,网络包接收计数器,磁
本文详细介绍了curl命令基础和高级用法,包括跳过https的证书验证,详细追踪整个交互过程,可用于调用网络后端接口,诊断http和https网络服务故障。
本文包含作者工作中常用到的一些命令,用于诊断网络、磁盘占满、fd泄漏等问题。命令包括ping、fping、tcpdump、lsof、netstat、/proc/$pid/fd、du、grep、traceroute、dig。
linux的平均负载表示运行态和就绪态及不可中断状态(正在io)的进程数目,用uptime查看到负载很高,既有可能是CPU利用率高,也可能是大量在等待io的进程导致,用mpstat查看每个CPU的使用情况,查看CPU的使用率或者CPU花在等待io的时间,接着用pidstat定位具体的进程
CPU上下文频繁切换会导致系统性能下降,切换分为进程切换、线程切换及中断切换,进程切换的开销较大,除了需要保存寄存器和程序计数器中的值还需保存全局变量、栈等到内存中,以便下次运行恢复,而同一进程中的线程切换开销会小很多,只需更新寄存器和线程独有的栈,共享资源如打开的文件、全局变量等无需切换,当硬件中
1.top命令 作用:该命令可以按CPU使用.内存使用和执行时间对任务进行排序,常用来监控系统中占用CPU或内存较高的程序及CPU和内存的负载。 默认视图: 当想看系统负载时,可观察汇总的%CPU中的us用户进程和sy系统进程是否占用CPU很高,相加接近100%就说明占用很高了,有些程序可能得不到及
文章浏览阅读1.8k次,点赞63次,收藏54次。Linux下的目录权限!!!粘滞位!!!超详解!!!
文章浏览阅读1.6k次,点赞44次,收藏38次。关于Qt的安装、Windows、Linux、MacBook_mack book 安装qt
本文介绍了使用shell脚本编写一个 Hello
文章浏览阅读1.5k次,点赞37次,收藏43次。【Linux】初识Linux——了解操作系统的发展历史以及初次体验Linux编程环境
文章浏览阅读3k次,点赞34次,收藏156次。Linux超详细笔记,个人学习时很认真的记录的,觉得好的麻烦点个赞。
文章浏览阅读6.8k次,点赞109次,收藏114次。【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.5p1(亲测无问题,建议收藏)_openssh_9.5p1
文章浏览阅读3.5k次,点赞93次,收藏78次。初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!
文章浏览阅读863次。出现此问题为Linux文件权限问题,解决方案为回到引擎目录执行命令。输入用户密码后运行./UnrealEditor。_increasing per-process limit of core file size to infinity.
文章浏览阅读2.9k次。使用文本编辑器:打开CSV文件,并使用文本编辑器(如Notepad++、Sublime Text、Visual Studio Code等)来查看文件的字符编码格式。通常在编辑器的底部状态栏或设置中可以找到当前编码的显示。请注意,上述方法并非绝对准确,特别是当文件没有明确的编码标识时。因此,如果你发现CSV文件在不同的工具或方法中显示不同的编码格式,可能需要进行进一步的分析和判断,或者尝试使用不同的编码转换方法。该命令将输出文件的MIME类型和编码信息。使用命令行工具:在命令行中,你可以使用。_shell读取csv文件逐行处理
本文介绍了如何在Linux系统中升级gcc版本,以便更好地支持C++11及以上版本的新特性。通过升级gcc,可以提升编译器的功能和性能,获得更好的开发体验。详细的步骤和方法请参考原文链接。
文章浏览阅读4.4k次,点赞6次,收藏19次。Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单,可以方便的来进行一些测试。_linux mosquitto
文章浏览阅读7.2k次,点赞2次,收藏12次。Linux中,用于根目录下有一个.ssh目录,保存了ssh相关的key和一些记录文件。_~/.ssh/
文章浏览阅读4.5k次,点赞5次,收藏18次。首先需要安装 snmp ,使用下面的命令进行安装安装完毕之后,使用下面的命令查看是否安装成功当命令行显示如图即为安装成功。_snmp工具