大幅重构内核模块
架构
目录结构
hal/ # 硬件抽象层 — 架构相关的启动/入口/异常陷入/上下文切换
loongarch/ # LoongArch: entry.S, trampoline.S, kernelvec.S, swtch.S, tlbrefill.S, uart.c
riscv/ # RISC-V: entry.S, trampoline.S, kernelvec.S, switch.S, start.c, uart.c, sbi.c
hsai/ # HSAI(硬件-软件抽象接口)— 异常处理、UART/PLIC、内存
kernel/ # 架构无关的内核代码 + driver/{loongarch,riscv}/ 下的架构相关驱动
driver/ # loongarch/: pci.c, virtio_disk.c, virtio_pci.c | riscv/: virt.c
fs/ # ext4 文件系统实现 + VFS 层(ext4, vfat)
user/ # 用户态 initcode(作为 PID 1 加载的最小程序)
include/ # 所有头文件,目录结构与源码树对应
sdcard-la.img #loongarc测试用例
sdcard-rv.img #riscv测试用例
多架构策略
架构选择通过代码中 编译期 #ifdef RISCV 实现。Makefile 在 RISC-V 构建时设置 -DRISCV=1;LoongArch 不设此标志(视为默认)。HSAI 层通过统一 API 抽象架构差异(hsai_trap_init、hsai_set_trapframe_*、hsai_swtch 等)。
启动流程
-
QEMU 加载内核并跳转到
hal/<arch>/entry.S中的_entry - Entry 阶段:设置 DMW(LoongArch)/ 跳转到
start(RISC-V),配置每 CPU 栈,清零 BSS,然后调用kernel/sos_start_kernel.c中的sos_start_kernel() -
sos_start_kernel()按顺序初始化各子系统:UART → 线程 → 进程 → 物理内存 (pmem) → 虚拟内存 (vmem) → slab 分配器 → 异常处理 → 磁盘 (VirtIO) → 文件系统 (ext4) → 创建首个用户进程 (init_process) → 进入调度器
进程与线程模型
-
进程(
proc_t,见process.h):最多NPROC=16,每个进程有页表、VMA 链表、文件表、信号处理和线程队列。状态转换:UNUSED → USED → RUNNABLE → RUNNING → SLEEPING/ZOMBIE。 -
线程(
thread_t,见thread.h):池大小为THREAD_NUM=1024。每个进程至少有一个主线程;通过clone(CLONE_VM)创建额外线程。每个线程有自己的内核栈和上下文。 -
调度器(
process.c中的scheduler()):简单的轮询调度,永不返回(__attribute__((noreturn)))。通过yield()/sched()实现主动上下文切换。
用户态/内核态切换(Trampoline)
Trampoline 页(trampoline.S)被映射到用户页表和内核页表的相同虚拟地址。陷入流程:用户寄存器保存到进程的 trapframe → 加载内核页表 → usertrap() 处理异常 → usertrapret() 准备返回 → trampoline 中的 userret 恢复用户上下文并执行 ertn/sret。
虚拟内存
-
vmem.c提供页表遍历、映射(mappages)、分配(uvmalloc)以及用户态/内核态之间的 copy-in/out - LoongArch 使用基于 DMW 的等值映射(虚拟地址高位置
0x9)—— 参见vmem.h中的to_vir()/to_phy() - RISC-V 使用标准 Sv39 页表,配合
mcmodel=medany
文件系统
-
VFS 层(
fs.h,fs.c)通过filesystem_op_t函数指针支持可插拔文件系统 -
ext4 是主文件系统,由
kernel/fs/ext4*.c实现标准 ext4 磁盘数据结构。VFS 操作位于kernel/fs/vfs_ext4.c -
vfat 有骨架支持(
vfs_vfat.c) - 块 I/O 经过缓冲区缓存(
bio.c,buf.h/BSIZE=4096)
系统调用
所有系统调用均在 kernel/syscall.c 中实现,该文件是单体文件(约 3000 行)。命名规范:每个系统调用为 sys_<名称>()。主要系统调用:openat、read/write/readv/writev、fork/clone/execve/wait/exit、mmap/munmap/mprotect/mremap、futex、socket 调用(socket/bind/connect/listen)、statx/fstatat/fstat、getdents64、mount/umount。
关键设计模式
-
自旋锁(
spinlock.c)通过acquire()/release()保护共享数据结构,在临界区中关闭中断 -
睡眠锁(
sleeplock.c)用于需要较长时间持有且允许进程睡眠的锁 -
睡眠/唤醒(
sleep_on_chan/wakeup)用于在任意地址上实现阻塞同步 - 错误码使用 Linux 风格的负 errno 值(
-ENOENT、-ENOMEM等)