一个 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_std | std |
---|---|---|
堆(动态内存) | * | ✓ |
集合(Vec、BTreeMap 等) | ** | ✓ |
堆栈溢出保护 | ✘ | ✓ |
在 main 之前运行初始化代码 | ✘ | ✓ |
libstd 可用 | ✘ | ✓ |
libcore 可用 | ✓ | ✓ |
编写固件、内核或引导加载程序代码 | ✓ | ✘ |
* 仅当您使用 alloc
箱子并使用合适的分配器(例如 alloc-cortex-m)时。
** 仅当您使用 collections
箱子并配置全局默认分配器时。
** 由于缺乏安全的随机数生成器,HashMap 和 HashSet 不可使用。