19.2 操作系统开发
本节是进入操作系统实践的路线说明,不是一个完整内核。读完后应能区分「不使用标准库」「生成目标代码」「在模拟器中启动」三个阶段,知道下一步需要补什么。
前置知识:Rust 所有权与错误处理、基本汇编、地址空间、中断,以及目标架构的调用约定。
19.2.1 内存安全需要有边界
安全 Rust 的检查可帮助防止悬挂引用等错误,但驱动、页表和内存映射经常需要原始指针或 unsafe。这些部分的正确性取决于实现者维护的约束,不能把「使用 Rust」等同于整个内核不会出错。死锁、资源泄漏、设备配置错误也不由借用检查器自动消除。
把危险操作封装成较小的接口,明确地址是否有效、访问是否对齐、对象何时失效、谁有权限写入,比笼统宣称完全安全更有用。
19.2.2 no_std 不是一个可以启动的操作系统
#![no_std] 使 crate 不依赖 std,仍可使用 core。它不自动提供堆分配器、文件系统、线程、TCP 栈或启动代码。是否需要 alloc、如何提供分配器,取决于项目设计。基础范围见 Embedded Rust Book
。
下面只是一个独立的逻辑库,保存为 tick.rs 后可检查其编译,不含入口、链接脚本和引导程序:
#![no_std]
pub fn next_tick(current: u64) -> Option<u64> {
current.checked_add(1)
}
rustc --edition=2021 --crate-type=lib tick.rs
即使这一步通过,也只能证明库能编译,不能宣告裸机内核可以启动。目标架构不同,还需要对应 target、链接布局、panic 处理与启动协议。关于独立程序的完整步骤,可参照 Writing an OS in Rust ,并固定所用教程与工具链版本。
19.2.3 把启动过程拆成可验收的阶段
| 阶段 | 应得到的结果 | 常见误判 |
|---|---|---|
| 生成镜像 | 链接成功,入口与地址布局符合引导协议 | 把普通宿主二进制当作内核镜像 |
| 最小启动 | 模拟器启动并产生串口或其他可观察输出 | 仅凭编译成功判断启动成功 |
| 内存与异常 | 分配、释放及异常处理有边界测试 | 只测试成功分配,不测试耗尽或非法访问 |
| 中断与设备 | 能处理重复中断、错误状态及超时 | 把一次正确输出当作稳定运行 |
| 调度与隔离 | 切换、取消与权限边界有验证 | 用语言的线程模型代替内核调度设计 |
每阶段保存工具链、target、模拟器版本、构建命令、启动命令和实际日志。涉及地址、页大小和寄存器的结论按目标架构分别核验。
19.2.4 从教学项目进入
rCore 教程 提供操作系统学习路线。开始前先读对应版本的环境要求,再按项目提供的方式构建;不要把另一套教程的架构、链接脚本和启动参数混进来。
第一次练习只追求一个可解释的结果:能启动、能输出、能说明控制权从哪里进入。之后再逐步进入异常、地址空间、进程与文件系统。没有阶段日志时,不把「某个项目用了 Rust」当作本机验证证据。
19.2.5 练习与检查点
- 说明上述
tick.rs与一个可启动内核之间还缺哪些部分。答案至少应包含入口、引导、目标架构和链接布局。 - 为内存分配器列出耗尽、重复释放、对齐三类验证场景。区分运行测试与
unsafe接口需要维护的安全条件。 - 在项目 README 中分别列出构建成功与启动成功的证据,避免把两者混写。
2026-10-12 修订:删除没有范围限定的安全与性能宣传,明确 no_std 和可启动内核的区别,补齐阶段验收与参考入口。本节没有声称已完成裸机启动实验。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。