最小化内核
内核仅包含最核心的服务:内存管理、任务调度、IPC 通信。其他功能(驱动、文件系统、网络)运行在用户空间。
OpenOS 采用微内核架构,这是现代操作系统设计的一种方法。与宏内核(如 Linux)不同,微内核仅在内核空间运行最核心的服务,而将驱动和大部分系统服务放在用户空间运行。
最小化内核
内核仅包含最核心的服务:内存管理、任务调度、IPC 通信。其他功能(驱动、文件系统、网络)运行在用户空间。
故障隔离
用户空间的驱动崩溃不会导致内核崩溃。每个服务运行在独立的地址空间中,相互隔离。
最小可信计算基
内核代码量小,更容易进行形式化验证和安全审计。seL4 微内核已经过形式化验证。
灵活的服务组合
服务可以独立重启、升级和替换。系统可以根据需要动态组合不同的服务。
┌─────────────────────────────────────────────────────────────┐│ 用户空间 (Ring 3) │├─────────────────────────────────────────────────────────────┤│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ 文件系统 │ │ 网络栈 │ │ 驱动程序 │ │ 显示服务 │ ││ │ 服务器 │ │ 服务器 │ │ │ │ │ ││ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ ││ │ │ │ │ ││ └──────────────┴──────────────┴──────────────┘ ││ │ IPC │├──────────────────────────┼──────────────────────────────────┤│ 内核空间 (Ring 0) │├─────────────────────────────────────────────────────────────┤│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ 内存管理 │ │ 任务调度 │ │ IPC 子系统 │ │ 中断处理 │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │├─────────────────────────────────────────────────────────────┤│ 硬件 │└─────────────────────────────────────────────────────────────┘OpenOS 内核由以下核心模块组成:
arch/x86_64/)负责 CPU 特定的初始化和管理:
| 模块 | 文件 | 职责 |
|---|---|---|
| GDT | gdt.rs | 全局描述符表,段选择子,TSS |
| IDT | interrupts.rs | 中断描述符表,异常和 IRQ 处理 |
| PIC | pic8259.rs | 可编程中断控制器初始化 |
| SYSCALL | syscall.rs | SYSCALL/SYSRET MSR 配置 |
drivers/)硬件抽象和输出:
| 驱动 | 文件 | 职责 |
|---|---|---|
| VGA | vga.rs | 帧缓冲文本渲染,8×16 位图字体 |
| 串口 | serial.rs | UART 16550 驱动,调试输出 |
memory/)| 模块 | 文件 | 职责 |
|---|---|---|
| 堆分配器 | allocator.rs | linked_list_allocator,100 KiB 堆 |
| 帧分配器 | frame_alloc.rs | 物理帧分配(bump 分配器) |
task/)| 模块 | 文件 | 职责 |
|---|---|---|
| 任务 | task.rs | TaskId(原子),TaskState,任务控制块 |
| 调度器 | scheduler.rs | 轮询调度器,就绪队列 |
handle.rs)| 模块 | 文件 | 职责 |
|---|---|---|
| Handle | handle.rs | Handle 结构体、Rights 位掩码、HandleTable |
| KernelObject | handle.rs | 内核对象枚举(ChannelEndA/B 等) |
ipc/)| 模块 | 文件 | 职责 |
|---|---|---|
| Channel | mod.rs | 同步会合消息传递 |
| EndState | mod.rs | Channel 端点状态,pending_handles |
syscall/)| 模块 | 文件 | 职责 |
|---|---|---|
| 分发器 | mod.rs | 22 个系统调用分发 |
| 编号 | number.rs | 系统调用号常量 |
elf.rs)| 模块 | 文件 | 职责 |
|---|---|---|
| ELF 解析 | elf.rs | ELF64 解析器,PT_LOAD 段加载 |
| Initrd | initrd.rs | Initrd 归档解析器 |
fs/)| 模块 | 文件 | 职责 |
|---|---|---|
| VFS | mod.rs | 虚拟文件系统占位符 |
BIOS → bootloader (0.11) → kernel_main() │ ├─ 1. VGA 初始化 (drivers/vga.rs) │ └─ 清屏,初始化帧缓冲 │ ├─ 2. 串口初始化 (drivers/serial.rs) │ └─ UART 16550 配置 │ ├─ 3. GDT + TSS (arch/x86_64/gdt.rs) │ └─ 段描述符,双重故障栈 │ ├─ 4. IDT (arch/x86_64/interrupts.rs) │ └─ 异常 + IRQ 处理函数 │ ├─ 5. PIC 初始化 (pic8259) │ └─ 重映射 IRQ 0-15 → INT 32-47 │ ├─ 6. 开启中断 (sti 指令) │ ├─ 7. 堆分配器 (memory/allocator.rs) │ └─ linked_list_allocator @ 0x4444_4444_0000 │ ├─ 8. Handle 系统 (handle.rs) │ └─ HandleTable,KernelObject │ ├─ 9. IPC 子系统 (ipc/mod.rs) │ └─ Channel 创建,消息传递 │ ├─ 10. 系统调用处理 (syscall/mod.rs) │ └─ 22 个系统调用分发器 │ ├─ 11. 任务调度器 (task/scheduler.rs) │ └─ 轮询调度,就绪/阻塞队列 │ ├─ 12. ELF 加载器 (elf.rs) │ └─ ELF64 解析,initrd 支持 │ ├─ 13. 用户空间服务 (task/user.rs) │ └─ Ring 3 切换,console_svc.elf │ └─ 14. 空闲循环 (hlt 指令)OpenOS 采用高半内核设计,内核映射在虚拟地址空间的高地址部分:
虚拟地址空间:0xFFFFFFFFFFFFFFFF ┌────────────────────┐ │ │ │ 内核空间 │ Ring 0 │ (高半) │0xFFFFFFFF80100000 ├────────────────────┤ ← 内核 .text │ .text / .rodata │ │ .data / .bss │ │ 堆 (100 KiB) │0xFFFFFFFF80000000 ├────────────────────┤ ← KERNEL_OFFSET │ │ │ (未映射间隙) │ │ │0x00007FFFFFFFFFFF ├────────────────────┤ ← 用户栈顶 │ 用户栈 │ Ring 3 │ (向下增长) │0x00007FFF00000000 ├────────────────────┤ │ │ │ 用户代码/数据 │ │ │0x0000000000400000 ├────────────────────┤ ← 用户程序基址 │ (保留/空) │0x0000000000000000 └────────────────────┘| 区域 | 虚拟地址 | 大小 | 权限 |
|---|---|---|---|
| VGA 文本缓冲区 | 0xB8000 | 4 KiB | RW(恒等映射) |
| 内核 .text | 0xFFFFFFFF80100000 | ~64 KiB | RX |
| 内核 .data/.bss | 0xFFFFFFFF80110000 | ~16 KiB | RW |
| 内核堆 | 0x4444_4444_0000 | 100 KiB | RW |
| 内核栈 (RSP0) | TSS.rsp0 | 32 KiB | RW |
| IST[0](双重故障) | TSS.ist[0] | 20 KiB | RW |
| 特性 | 微内核 (OpenOS) | 宏内核 (Linux) |
|---|---|---|
| 内核大小 | 小 (~100 KiB) | 大 (~10 MiB) |
| 驱动位置 | 用户空间 | 内核空间 |
| 故障隔离 | 强(驱动崩溃不影响内核) | 弱(驱动崩溃导致内核崩溃) |
| IPC 开销 | 高(消息传递) | 低(函数调用) |
| 可验证性 | 高(代码量小) | 低(代码量大) |
| 性能 | 中等(IPC 开销) | 高(直接调用) |
| 灵活性 | 高(服务可独立更新) | 低(需要重新编译内核) |
详细的设计决策请参考 架构决策记录。
关键决策包括: