共计 4541 个字符,预计需要花费 12 分钟才能阅读完成。
一、目标与范围(Stage 0:立项)
- 架构:x86_64(BIOS/UEFI)或 RISC-V(S/HS 模式)。
- 模式:
no_std、no_main、内核态单地址空间起步。 - 运行方式:QEMU + 串口日志 + GDB 远程调试。
- 最小可行成果:上电→进入内核→打印日志→定时器中断→安全关机 / 重启。
二、工具链与构建(Stage 0)
- Rust:nightly;
-Z build-std=core,alloc;目标三元组x86_64-unknown-none/riscv64imac-unknown-none-elf。 - 引导:
- x86_64:
bootloadercrate 或自编 2 阶段引导(UEFI 可用ueficrate)。 - RISC-V:OpenSBI + 内核镜像。
- x86_64:
- 模拟与调试:QEMU(
-serial mon:stdio)、GDB、llvm-objdump/objcopy、cargo-bootimage(如选 bootloader)。 - CI:Headless QEMU 自测、
cargo clippy、cargo fmt。
三、目录结构(建议)
kernel/
├─ Cargo.toml
├─ build.rs
└─ src/
├─ lib.rs // 入口、panic、日志
├─ arch/
│ ├─ mod.rs
│ ├─ x86_64/
│ │ ├─ boot.rs, gdt.rs, idt.rs, pit_apic.rs, paging.rs
│ └─ riscv/
│ ├─ boot.rs, trap.rs, clint_plic.rs, paging.rs
├─ mm/ // 物理 / 虚拟内存、分配器
├─ sync/ // 自旋锁、原子、屏障
├─ intr/ // 中断 / 异常 / 定时器
├─ sched/ // 任务、调度、上下文切换
├─ syscall/ // ABI、入口 / 返回
├─ drivers/ // 串口、时钟、块 / 网卡 /PCIe
├─ fs/ // VFS/ 缓存 / 具体 FS
├─ ipc/ // 管道、消息、共享内存
├─ net/ // 协议栈(可选)└─ userland/ // 简单用户态程序与启动
四、最小内核骨架(可直接扩展)
// src/lib.rs
#![no_std]
#![no_main]
#![feature(alloc_error_handler)]
extern crate alloc;
use core::panic::PanicInfo;
#[no_mangle]
pub extern "C" fn _start() -> ! {arch::early_init(); // 关中断、基础寄存器、BSS 清零(若需)mm::init_memory(); // 建页表、映射内核、启用分页、init 全局分配器
intr::init(); // IDT/Trap 向量、时钟中断
drivers::early_uart_init();
log::info!("kernel online 🚀");
sched::init();
arch::enable_interrupts();
// 心跳:每秒打印一次时间戳 / 滴答
loop {sched::idle(); }
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {log::error!("kernel panic: {info}");
arch::halt_loop()}
#[alloc_error_handler]
fn oom(_: core::alloc::Layout) -> ! {log::error!("OOM in kernel allocator");
arch::halt_loop()}
五、启动与早期平台(Stage 1)
- x86_64:GDT/TSS、IDT、分页(4-level/5-level)、APIC/HPET、SMP 启动(AP 牵引)。
- RISC-V:
satp开启分页、stvec/sscratch设置、CLINT(时钟)/PLIC(外部中断)、SMP 核心拉起。 - 串口:UART 驱动(x86_64 可 MMIO/IO-port;RISC-V 16550/QEMU virtio-console)。
六、内存管理(Stage 2)
- 物理页帧分配器:位图 / 段树;保留内核镜像、设备内存、页表。
- 虚拟内存:多级页表抽象(x86_64 PML4/LA57;RISC-V Sv39/48);内核高半区映射。
- 堆分配器:基于
alloc的全局分配器(linked-list、buddy、slab 任一);内核对象 slab。 - 安全:W^X、栈保护、内核地址随机化(后续)。
关键接口
pub trait FrameAllocator {fn alloc(&self, order: usize) -> Option<PhysAddr>;
fn free(&self, addr: PhysAddr, order: usize);
}
pub unsafe trait PageTable {fn map(&mut self, v: VirtAddr, p: PhysAddr, flags: MapFlags);
fn unmap(&mut self, v: VirtAddr);
}
七、中断与时间(Stage 3)
- 异常 / 中断入口:保存陷入上下文、错误码解析、可重入 / 嵌套策略。
- 定时器:PIT/HPET/APIC timer 或 RISC-V
mtime;节拍器 tick 或 tickless。 - 时钟源:单调时钟、墙钟、调度时钟。
八、同步与并发(Stage 3)
- 原语:自旋锁、屏障、禁中断临界区、
Atomic*。 - 不可阻塞日志:环形缓冲 + 串口后台刷写。
九、任务与调度(Stage 4)
- 任务模型:内核线程起步,后续引入进程 / 地址空间。
- 上下文切换:保存通用寄存器、栈指针、返回地址;延迟调度。
- 调度算法:RR/SJF/CFS 任选其一作为起点;可插拔策略接口。
- SMP:每核 runqueue、负载均衡、IPI(核间中断)。
十、系统调用与用户态(Stage 5)
- ABI:x86_64(
syscall/sysret或int 0x80),RISC-V(ecall)。 - 边界:从用户到内核的参数校验、复制(
copy_from_user/copy_to_user)。 - 进程地址空间:ELF 加载器、栈 / 堆映射、按需缺页(后续)。
十一、驱动框架(Stage 6)
- 总线与设备模型:PCIe/virtio/AMBA;驱动注册与生命周期(probe/remove/power)。
- 必须设备:串口、定时器、RTC、块设备(virtio-blk)、网卡(virtio-net)、简单帧缓冲。
- DMA 与内存一致性:IOMMU(高级阶段)。
十二、VFS 与文件系统(Stage 7)
- VFS 抽象:inode、dentry、superblock、文件描述符、poll/epoll 接口。
- 首个 FS:FAT32 或 Ext2;页面缓存、回写策略;ramfs 作为引导盘。
十三、IPC 与同步(Stage 8)
- 机制:管道、消息队列、共享内存、futex;信号 / 事件通知。
- 命名空间 / 隔离:PID/ 挂载 / 网络命名空间(进阶)。
十四、网络子系统(可选,Stage 9)
- 驱动:virtio-net。
- 协议栈:ARP、IPv4、ICMP、UDP→TCP;socket API(最小子集)。
十五、安全(横切)
- 权限模型:用户 / 组 / 能力(capabilities)。
- 内存防护:SMEP/SMAP/UMIP(x86_64);页表权限严格化;栈金丝雀。
- 系统调用过滤:基于策略的 allowlist。
十六、可观测性与调试(横切)
- 日志:级别与分类;串口 / 环形缓冲;早期日志与后期日志合并。
- 跟踪:事件探针、周期采样;panic dump、栈回溯、符号化。
- 性能:简单 profiler、计数器(分配 / 缺页 / 切换 / 中断)。
十七、电源管理与多核(进阶)
- SMP 完备:AP 拉起顺序、IPI 服务、TSC 同步(x86_64)。
- Idle/ 频率:C-state/P-state(或 RISC-V WFI 策略)。
- 挂起 / 休眠:内存镜像与恢复(后续)。
十八、虚拟化(可选,远期)
- x86_64:VMX/SVM;最小型 VMM。
- RISC-V:H 扩展;Trap & Emulate。
十九、测试与验证
- 单元测试:
#[cfg(test)]+ 自定义 test runner(在 QEMU 内跑)。 - 集成测试:启动→跑用例→串口比对输出→退出 QEMU(
isa-debug-exit)。 - 性质测试:快速检查器(property-based)。
- 模糊:syscall/ELF 加载器 输入模糊。
最小“能跑”的两个模块草图
1) 串口日志(drivers/uart.rs)
use core::fmt::{self, Write};
use spin::Mutex;
pub struct Uart16550 {base: u16}
static UART: Mutex<Option<Uart16550>> = Mutex::new(None);
impl Write for Uart16550 {fn write_str(&mut self, s: &str) -> fmt::Result {for b in s.bytes() {unsafe { outb(self.base, b); } }
Ok(())
}
}
pub fn init(base: u16) {*UART.lock() = Some(Uart16550 { base}); }
pub fn print(args: fmt::Arguments) {if let Some(u) = UART.lock().as_mut() {let _ = u.write_fmt(args); }
}
#[macro_export] macro_rules! kprintln {($($arg:tt)*) => ($crate::drivers::uart::print(format_args!($($arg)*)));
}
2) 页帧分配器雏形(mm/frame.rs)
use core::sync::atomic::{AtomicUsize, Ordering::*};
pub struct BitmapFrames {
base: usize,
nframes: usize,
bitmap: &'static mut [u64],
}
impl BitmapFrames {pub fn alloc(&mut self) -> Option<usize> {for (i, w) in self.bitmap.iter_mut().enumerate() {
if *w != u64::MAX {let bit = (!*w).trailing_zeros() as usize;
*w |= 1 << bit;
return Some(self.base + ((i * 64 + bit) << 12));
}
}
None
}
pub fn free(&mut self, addr: usize) {let idx = (addr - self.base) >> 12;
self.bitmap[idx / 64] &= !(1 << (idx % 64));
}
}
里程碑路线图(浓缩版)
- Stage 0–1:引导 → 分页 → 串口日志 → 定时器中断(QEMU 可运行)。
- Stage 2:页帧 + 虚拟内存 + 内核分配器;基础同步。
- Stage 3–4:异常 / 中断完备 → 任务 / 调度 → SMP。
- Stage 5:系统调用 + 用户态 ELF;简易
init。 - Stage 6–7:驱动框架 + VFS + 一个文件系统。
- Stage 8+:IPC、网络、安全、可观测性;之后再考虑虚拟化 / 休眠。
正文完

