Skip to content

大幅重构内核模块

S-OS队 requested to merge master into main

架构

目录结构

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_inithsai_set_trapframe_*hsai_swtch 等)。

启动流程

  1. QEMU 加载内核并跳转到 hal/<arch>/entry.S 中的 _entry
  2. Entry 阶段:设置 DMW(LoongArch)/ 跳转到 start(RISC-V),配置每 CPU 栈,清零 BSS,然后调用 kernel/sos_start_kernel.c 中的 sos_start_kernel()
  3. 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_<名称>()。主要系统调用:openatread/write/readv/writevfork/clone/execve/wait/exitmmap/munmap/mprotect/mremapfutex、socket 调用(socket/bind/connect/listen)、statx/fstatat/fstatgetdents64mount/umount

关键设计模式

  • 自旋锁spinlock.c)通过 acquire()/release() 保护共享数据结构,在临界区中关闭中断
  • 睡眠锁sleeplock.c)用于需要较长时间持有且允许进程睡眠的锁
  • 睡眠/唤醒sleep_on_chan/wakeup)用于在任意地址上实现阻塞同步
  • 错误码使用 Linux 风格的负 errno 值(-ENOENT-ENOMEM 等)

Merge request reports