一个从零编写的 x86_64 长模式操作系统内核学习项目。
CoreZ OS 是一个用于学习操作系统原理的教学型内核,从 16 位实模式引导扇区起步,经 加载器进入保护模式并开启长模式,最终运行一个支持多任务、用户进程、文件系统与 网络的 64 位内核。
当前内核已能在 QEMU 中稳定引导与运行:图形化 Boot Menu(VBE 1024x768 + KASLR)、
多任务与抢占式调度、COW fork 的用户进程、ext2 文件系统、/proc 伪文件系统、
TCP/UDP 网络栈、简易 GUI 合成器,以及一个可执行内置命令与用户程序的 shell。
| 模块 | 说明 |
|---|---|
| 引导 (Boot) | boot.asm:512 字节主引导扇区,从硬盘分区加载 loader |
| 加载器 (Loader) | loader.asm:FAT32 读取内核、VBE 图形模式、E820 内存探测、Boot Menu(倒计时/上下键选择 + 重启项)、KASLR 内核加载地址随机化、进入保护模式 → 长模式、构造 Multiboot2 信息 |
| 中断 | initer/idt:256 门 IDT,ring3 异常转信号(SIGSEGV 等),COW 缺页处理 |
| 中断控制器 | initer/apic:Local APIC + IPI + LAPIC 定时器(校准 per-tick);initer/pic/pit:PIC + PIT 回退路径 |
| ACPI | initer/acpi:RSDP/RSDT/FADT 探测与 ACPI 使能 |
| SMP | initer/smp:AP trampoline(低 1MB 实模式跳板)+ INIT/SIPI 唤醒 + 每 CPU GDT/栈 |
| 屏幕输出 | initer/io:VBE 线性帧缓冲上绘制字库文本,kprintf/console_putc,debugcon (0xE9) 镜像输出 |
| 模块 | 说明 |
|---|---|
| 物理内存池 | memory/pool:E820 探测 + 位图管理物理页框,palloc/pfree/palloc_pages,mem_lock 保护 |
| 内核虚拟地址池 | KERNEL_VADDR_START 起的 vaddr 位图,ioremap 设备映射(NX/PCD) |
| 内核堆 | get_kernel_pages:高半区(VIRT_OF = phys + 0xC0000000)直接映射分配 |
| COW fork | userprog/fork:页表遍历复制,写时复制(COW_FLAG + 引用计数 frame_owner),缺页时 page_cow_resolve 原子完成决策/拷贝/递减 |
| 用户地址空间 | 每进程独立 PML4 + 用户 vaddr 位图;mmap/brk 堆扩展 |
| 模块 | 说明 |
|---|---|
| 线程/进程 | thread:任务槽(MAX_TASKS=64,可回收)+ 红黑树就绪队列 + 时间片抢占调度,DIED 线程由调度器统一回收(栈/页目录/槽位) |
| 用户进程 | userprog/process:ring3(intr_exit 模拟中断返回)、TSS、TLS(set_thread_area) |
| fork/clone | userprog/fork、userprog/clone:COW 地址空间复制;clone 共享页目录与 fd 表(线程语义) |
| exec | userprog/exec:ELF32/ELF64 加载、辅助向量(auxv)、参数/环境入栈、W^X(可执行段 RX) |
| 退出/等待 | userprog/wait_exit:资源释放、孤儿进程自动终止回收、wait/waitpid |
| 模块 | 说明 | |
|---|---|---|
| 同步原语 | thread/sync:信号量、可重入锁(holder/holder_repeat_nr 由信号量自带 spinlock 保护,多核安全)、自旋锁 |
|
| 系统调用 | syscall:int 0x80(原生 ABI)+ syscall 指令路径 + musl 兼容层(linux_compat.c);ring0 内核线程调用与 ring3 用户调用分别校验(access_ok 仅约束用户指针) |
|
| 信号 | syscall/signal:SIGSEGV/SIGINT 等常用信号、sigaction/sigprocmask/sigreturn、Ctrl+C 终止前台进程 |
|
| futex | syscall/futex:FUTEX_WAIT/WAKE |
|
| 文件系统 | fs/ext2:ext2 只读元数据 + 读写的完整实现(inode/块分配释放、目录项增删、间接块、truncate),全局可重入锁串行化元数据操作 |
|
| 伪文件系统 | fs/proc:/proc/meminfo |
|
| 文件表 | fs/file:全局 file 表 + 每进程 fd 表,引用计数(fork/clone/dup 共享),file_table_lock 保护槽位分配 |
|
| 管道 | shell/pipe:ioqueue 实现的匿名管道,pipe/fd_redirect,shell 支持 `cmd1 |
cmd2` |
| inode 缓存 | fs/inode:每分区红黑树缓存打开的 inode(i_open_cnt 引用计数,开/关中断对称保护) |
| 模块 | 说明 |
|---|---|
| 键盘 | device/keyboard:8042 扫描码 → keymap(shift/caps/ctrl/alt),ioqueue 缓冲,GUI hook |
| 鼠标 | device/mouse:PS/2 aux 通道,三字节包解析 |
| 网卡 | net/e1000:PCI 探测、MMIO 寄存器、TX/RX 描述符环 |
| 网络栈 | net:Ethernet/ARP/IP/ICMP/TCP/UDP + BSD socket API(socket/bind/connect/send/recv/select),QEMU user 网络下 DHCP 式自动配置 10.0.2.15 |
| GUI | gui:简易合成器(窗口合成、鼠标、键盘事件分发),shell 输入 gui 进入 |
内置命令:ls cd pwd mkdir rmdir rm clear ps gui shutdown;
支持外部程序执行与管道。
src/command/ 下的用户程序(由内核 libc 编译为 ELF):
| 程序 | 演示内容 |
|---|---|
prog_no_arg / prog_arg |
基本执行 / 参数传递 |
fork_demo / orphan_demo |
fork / 孤儿进程回收 / wait(NULL) |
cow_stress |
COW 压力测试 |
prog_pipe |
管道 |
heap_demo / mmap_demo / mmap2_demo |
堆与 mmap |
signal_demo / futex_demo / clone_demo |
信号 / futex / clone 线程 |
cwd_test |
getcwd 边界 |
cat |
文件读取(支持 /proc/meminfo) |
ping / udp_echo |
ICMP ping / UDP 回显服务 |
nr_shell |
移植的 nr_micro_shell |
font_demo |
TTF 字体渲染 |
src/app/ 下另有 musl 源码(--with-musl-lib 构建完整 libc 并运行
libc-testsuite)与第三方代码(mongoose)。
CoreZOS/
├── build.py # 构建系统(探测工具链、并行编译、打包镜像、启动 QEMU)
├── linker/kernel.ld # 内核链接脚本
├── scripts/
│ ├── make_ext2.py # 生成 test_hd.img(FAT32 引导分区 + ext2 数据分区)
│ └── mkfloppy.py # 软盘镜像
└── src/
├── boot/ # boot.asm 引导扇区 + loader.asm(VBE/KASLR/长模式)
├── command/ # 用户测试程序(见上表)
└── kernel/
├── main.c # kmain:初始化序列(mm/gdt/tss/idt/syscall/apic/acpi/...)
├── asmCall/ # entry/switch/stub/func 等汇编
├── device/ # keyboard/mouse/ide/ioqueue
├── fs/ # ext2/file/inode/dir/proc
├── gui/ # 合成器/gfx/server/wm/clients
├── include/ # 公共头(asmFunc.h、stub.h 等)
├── initer/ # io/gdt/tss/idt/apic/pic/pit/acpi/smp
├── lib/ # str/list/rbtree/bitmap + 用户态 libc(lib/user)
├── memory/ # pool/bitmap/access(copy_from_user 等)
├── net/ # e1000/eth/arp/ip/icmp/tcp/udp/socket
├── shell/ # shell/pipe/buildin_cmd
├── syscall/ # syscall/file_syscall/signal/futex/mmap/linux_compat
├── thread/ # thread/sync/percpu
└── userprog/ # process/fork/clone/exec/wait_exit
nasm—— 汇编(elf64/bin)zig cc(或 gcc/clang 交叉)—— C 编译(freestanding)ld.lld/ld—— 链接python3—— 构建系统与镜像脚本qemu-system-x86_64—— 运行验证
python3 build.py # 构建内核与 floppy.img
python3 build.py run # 构建并在 QEMU 中启动(自动生成 test_hd.img)
python3 build.py run --sm 2 # SMP 启动验证
python3 build.py run --gdb # GDB stub (-s -S),配合 build/kernel.elf 调试
python3 build.py cleanrun 默认以 build/test_hd.img 硬盘镜像引导(自动生成:P1 FAT32 引导分区 +
P2 ext2 数据分区,并写入用户程序);--boot-floppy 可改用软盘镜像。
--with-musl-lib 会额外编译完整 musl libc 并构建 libc-testsuite。
启动后进入 Boot Menu(5 秒倒计时,上下键/数字键选择,回车立即引导)。 进入 shell 后可直接使用内置命令或运行用户程序,例如:
corez@corez /$ ls
corez@corez /$ fork_demo.elf
corez@corez /$ cat.elf /proc/meminfo
corez@corez /$ gui
QEMU 参数默认挂载 e1000 网卡 + user 网络后端(hostfwd tcp::8765-:8765),
内核自动配置 10.0.2.15,可用 ping.elf 测试连通性。
内核所有 kprintf/控制台输出会同步镜像到 QEMU debugcon(端口 0xE9),
-debugcon stdio/file:... 可在终端或文件中查看内核日志,便于无头调试。
- 用户 fork 的子进程在进入用户态后触发 SIGSEGV(退出码 139),fork 子进程侧 功能暂不可用;父进程路径与 COW 建页正常。与 exec 的 W^X / COW / NX 互作用有关。
- e1000 初始化在大规模内存分配压力下可能缺页(
ioremap的映射丢失,原因待查), 正常负载下网络工作正常。 - ext2 与 file_table 采用粗粒度全局锁,正确性优先、吞吐串行化。
- OSDev Wiki https://wiki.osdev.org —— 引导、GDT/IDT、APIC、长模式、Multiboot2 等。
- musl libc https://musl.libc.org —— 系统调用 ABI 兼容目标与 libc 测试套件。
- 长模式内核:引导(VBE/KASLR/Boot Menu)、中断、APIC/ACPI、SMP 框架
- 内存管理:物理池、内核虚拟地址池、ioremap、用户地址空间
- 进程:线程/进程、抢占调度、COW fork、clone、exec(ELF32/64)、wait/孤儿回收
- 同步:信号量、可重入锁、futex、信号
- 文件系统:ext2(读写)、/proc、管道、dup/fd 引用计数
- 网络:e1000 + ARP/IP/ICMP/TCP/UDP + socket API
- GUI 合成器、shell 与用户程序集
- 修复 fork 子进程 SIGSEGV(见已知问题)
- 内核堆分配器(malloc 形态的细粒度分配)
- 多核调度(AP 目前仅验证可启动,未参与调度)
- 重新加入 musl 的构建选项