一个 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 环境中进行编码。
裸机环境
在裸机环境中,你的程序之前没有加载任何代码。如果没有操作系统提供的软件,我们就无法加载标准库。相反,该程序及其使用的 crate 只能使用硬件(裸机)来运行。要阻止 rust 加载标准库,请使用 no_std
。标准库中与平台无关的部分可以通过 libcore 获得。libcore 还排除了在嵌入式环境中不总是需要的东西。其中一件是用于动态内存分配的内存分配器。如果你需要这个或任何其他功能,通常会有 crate 提供这些功能。
libstd 运行时
如前所述,使用 libstd 需要某种系统集成,但这不仅是因为 libstd 只是提供了一种访问 OS 抽象的通用方法,它还提供了一个运行时。此运行时除其他外,负责设置堆栈溢出保护、处理命令行参数以及在调用程序的 main 函数之前生成主线程。此运行时在 no_std
环境中也无法使用。
总结
#![no_std]
是一个 crate 级别的属性,指示该 crate 将链接到 core-crate 而不是 std-crate。 libcore crate 反过来是 std crate 的一个与平台无关的子集,它对程序将在其上运行的系统不做任何假设。因此,它为语言原语(如浮点数、字符串和切片)以及暴露处理器特性(如原子操作和 SIMD 指令)的 API 提供了 API。但是,它缺少任何涉及平台集成的 API。由于这些特性,no_std 和 libcore 代码可以用于任何类型的引导(第 0 阶段)代码,如引导加载程序、固件或内核。
概览
特性 | no_std | std |
---|---|---|
堆(动态内存) | * | ✓ |
集合 (Vec, BTreeMap 等) | ** | ✓ |
堆栈溢出保护 | ✘ | ✓ |
在 main 之前运行初始化代码 | ✘ | ✓ |
libstd 可用 | ✘ | ✓ |
libcore 可用 | ✓ | ✓ |
编写固件、内核或引导加载程序代码 | ✓ | ✘ |
* 仅当您使用 alloc
crate 并使用合适的分配器,例如 alloc-cortex-m 时。
** 仅当您使用 collections
crate 并配置全局默认分配器时。
** 由于缺少安全的随机数生成器,HashMap 和 HashSet 不可用。