学习目标 🎯
- 在 macOS 上搭建完整的 Rust 操作系统开发环境
- 配置 macOS 特有的开发工具
- 成功编译并运行第一个内核程序
第一部分: macOS 开发环境准备
安装 Rust 必要组件
Rust
版本 1.70.0 (稳定版本)
bash
# 安装 Rust 源码
rustup component add rust-src
# 安装Rust nightly工具链(必需不稳定特性)
rustup install nightly
rustup default nightly
# 添加编译目标(生成裸机二进制)
rustup target add x86_64-unknown-none
# 安装 LLVM 工具
rustup component add llvm-tools-preview
# 安装 bootimage 工具
cargo install bootimage
# 验证安装
bootimage --version
rust-src
rust-src
是 Rust 编程语言的源代码包,它包含了 Rust 标准库和编译器的完整源代码。
nightly
nightly
是 Rust 编程语言的每日构建版本,它包含了最新的、尚未稳定的功能和改进。 在这里用最新版。
为什么需要 nightly
?
bootloader
编译需要-Z
标志 (-Z
是Rust
编译器的不稳定标志,用于启用实验性功能和内部选项。)- 裸机开发需要最新的编译器功能
- 工具链支持需要实验性功能
x86_64-unknown-none
x86_64-unknown-none
是面向64 位 x86 架构裸机环境的目标标识,用于无操作系统的开发场景(如内核、嵌入式系统)。
llvm-tools-preview
llvm-tools-preview
是 Rust 生态系统中的一个组件,它提供了 LLVM 工具链的预览版本。 包含的工具有:
llvm-objcopy
:用于复制和修改目标文件llvm-objdump
:用于显示目标文件信息llvm-readelf
:用于读取 ELF 文件格式llvm-strip
:用于去除符号表llvm-size
:用于显示目标文件大小- 其他
LLVM
工具
在 Rust
项目中的作用:
- 用于交叉编译
- 处理目标文件
- 调试和优化
- 嵌入式开发
bootimage
bootimage 是一个 Rust 工具,专门用于创建可引导的磁盘镜像。它主要用于操作系统开发和嵌入式系统开发。bootimage 在这个项目中特别有用:
- 将Rust 内核编译成可引导镜像
- 在 QEMU 虚拟机中测试内核
- 创建用于实际硬件部署的镜像
第二部分:安装 QEMU
1. 使用 Homebrew 安装 QEMU
bash
# 安装 QEMU(推荐方法)
brew install qemu
# 验证安装
qemu-system-x86_64 --version
which qemu-system-x86_64
2. 配置 QEMU 路径
bash
# 检查 QEMU 安装路径
ls -la /opt/homebrew/bin/qemu* # Apple Silicon Mac
# 添加到 PATH(通常 Homebrew 会自动处理)
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc # Apple Silicon
3. 测试 QEMU
bash
# 测试 QEMU 是否正常工作
qemu-system-x86_64 -version
QEMU (Quick EMUlator)
是一个开源的硬件虚拟化工具,可以模拟不同的计算机硬件架构。
QEMU
的主要功能:
- 硬件模拟
- 模拟 CPU、内存、硬盘、网络等硬件
- 支持多种架构:x86_64、ARM、PowerPC 等
- 提供虚拟的计算机环境 2. 系统虚拟化
- 运行完整的操作系统
- 支持 Windows、Linux、macOS 等
- 提供隔离的虚拟环境 3. 用户模式模拟
- 运行单个程序
- 跨架构程序执行
- 调试和测试工具
QEMU
的优势
- 跨平台支持
- 在 macOS 上运行 Linux 程序
- 在 ARM 机器上运行 x86_64 代码
- 支持多种操作系统 2. 性能优秀
- 接近原生性能
- 支持硬件加速
- 高效的模拟 3. 功能丰富
- 网络支持
- 图形界面
- 调试工具
常用 QEMU
命令
- 基本运行
bash
qemu-system-x86_64 -drive format=raw,file=kernel.bin
- 指定内存
bash
qemu-system-x86_64 -m 512M -drive format=raw,file=kernel.bin
- 启用图形界面
bash
qemu-system-x86_64 -display gtk -drive format=raw,file=kernel.bin
- 网络支持
bash
qemu-system-x86_64 -net nic -net user -drive format=raw,file=kernel.bin
第三部分 创建项目
bash
cargo new blog_os --bin
cd blog_os
修改 Cargo.toml
添加配置:
toml
[package]
name = "blog_os"
version = "0.1.0"
edition = "2021" # 兼容较旧版本
[dependencies]
bootloader = "0.9" # 引导加载程序
[build-dependencies]
bootimage = "0.10.3" # 镜像创建工具
修改 main.rs
rust
// 1. 禁用标准库
#![no_std]
// 2. 禁用Rust运行时(无main函数)
#![no_main]
// 3. 定义入口点(取代main函数)
#[no_mangle]
pub extern "C" fn _start() -> ! {
// 内核入口函数
loop {}
}
// 4. 实现panic处理函数
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
第四部分:编译和运行
bash
# 编译内核
cargo +nightly build --target x86_64-unknown-none
# 运行内核 (直接运行 ELF 文件)
qemu-system-x86_64 -drive format=raw,file=target/x86_64-unknown-none/debug/blog_os
此时:

写在最后-电脑开机启动发生了什么
开机启动流程
- POST(加电自检)
- 进行一系列诊断
- 按固件配置顺序寻找可启动设备(软盘、CD-ROM、硬盘等)
- 主引导记录(MBR)
- BIOS检查引导扇区的引导签名(0x55、0xAA,位于510和511字节偏移处)
- 找到后加载到内存特定位置(0x0000:0x7c00或0x7c0:0x0000,物理地址相同) -硬盘MBR结构:446字节可执行代码 + 分区表(16字节/项,共4项) + 2字节签名
- 早期执行环境
- 高度依赖BIOS实现,寄存器内容不确定(包括FLAGS、SP,栈可能无效)
- 唯一确定:DL寄存器存引导代码加载的驱动器代码
- CPU通常处于实模式(少数BIOS可能已激活保护模式)
- 内核加载与控制转移
- 引导程序加载内核到内存并移交控制权 内核加载前的任务
- 确定启动分区(找活动分区或让用户选择)
- 确定内核在引导分区的位置(解析文件系统或从固定位置加载)
- 加载内核到内存(需基础磁盘I/O)
- 启用保护模式
- 为内核准备运行环境(如设置栈空间) 解决引导记录空间限制的方法
- 极客加载:将所有任务挤入引导记录(几乎不可能,无特殊处理和错误信息空间)
- 单阶段加载:写转换存根程序链接到内核前,引导记录加载内核到1MB以下,存根切换到保护模式并准备环境后跳转内核
- 两阶段加载:写单独存根程序加载到1MB以下,完成所有加载前任务
- 传统链式加载:MBR relocation到0x0000:0x0600,加载活动分区引导记录到0x0000:0x7c00并跳转 推荐与其他启动方式
- 推荐使用现成引导程序(如GRUB)
- 提供启动菜单和链式加载功能
- 初始化早期环境到确定状态(含保护模式、读取BIOS信息)
- 支持多种文件系统、内核模块、无盘启动等
- 其他启动方式
-
利用未使用分区加载第二阶段
-
将第二阶段放在MBR和第一个分区起始之间
-
类似Lilo:检测扇区/簇列表,第一阶段加载对应扇区
-
DOS和Windows:格式化空文件系统,加载根目录第一、二个文件
-
旧Linux软盘启动:第一扇区加载第二阶段(setup),其设置系统后加载内核
-
nuni引导程序:在一个引导扇区内切换到保护模式并加载文件
-