一个 no_std Rust 环境

嵌入式编程一词用于各种不同的编程类别。从仅使用几 KB RAM 和 ROM 的 8 位 MCU(例如 ST72325xx)编程,到像 Raspberry Pi (Model B 3+) 这样的系统,它拥有 32/64 位 4 核 Cortex-A53 @ 1.4 GHz 和 1GB RAM。根据您的目标和用例,编写代码时会应用不同的限制/局限性。

嵌入式编程一般分为两类

托管环境

这类环境类似于普通 PC 环境。这意味着您将获得一个系统接口(例如 POSIX),它为您提供与各种系统交互的原语,例如文件系统、网络、内存管理、线程等。标准库通常依赖于这些原语来实现其功能。您可能还有一些 sysroot 和对 RAM/ROM 使用的限制,以及一些特殊的硬件或 I/O。总的来说,它感觉像是用特殊用途的 PC 环境进行编码。

裸机环境

在裸机环境中,您的程序之前没有加载任何代码。没有操作系统提供的软件,我们就无法加载标准库。相反,程序及其使用的箱子只能使用硬件(裸机)来运行。为了防止 Rust 加载标准库,请使用 no_std。标准库中与平台无关的部分可以通过 libcore 使用。libcore 还排除了在嵌入式环境中并不总是理想的功能。其中之一是用于动态内存分配的内存分配器。如果您需要此功能或任何其他功能,通常会有提供这些功能的箱子。

libstd 运行时

如前所述,使用 libstd 需要某种系统集成,但这不仅仅是因为 libstd 只是提供了一种访问操作系统抽象的通用方式,它还提供了一个运行时。这个运行时除了其他功能之外,还负责设置堆栈溢出保护、处理命令行参数,并在调用程序的主函数之前生成主线程。这个运行时在 no_std 环境中也不可用。

总结

#![no_std] 是一个箱子级属性,它指示箱子将链接到 core-crate 而不是 std-crate。libcore 箱子反过来是 std 箱子的一个与平台无关的子集,它对程序将运行的系统没有任何假设。因此,它提供了用于浮点数、字符串和切片等语言原语的 API,以及用于公开处理器功能(如原子操作和 SIMD 指令)的 API。但是,它缺少涉及平台集成的 API。由于这些特性,no_std 和 libcore 代码可用于任何类型的引导(阶段 0)代码,例如引导加载程序、固件或内核。

概述

功能no_stdstd
堆(动态内存)*
集合(Vec、BTreeMap 等)**
堆栈溢出保护
在 main 之前运行初始化代码
libstd 可用
libcore 可用
编写固件、内核或引导加载程序代码

* 仅当您使用 alloc 箱子并使用合适的分配器(例如 alloc-cortex-m)时。

** 仅当您使用 collections 箱子并配置全局默认分配器时。

** 由于缺乏安全的随机数生成器,HashMap 和 HashSet 不可使用。

另请参阅