tianole/docs/agents/tasks/07-user-mode.md

4.7 KiB
Raw Permalink Blame History

07 用户态、系统调用与进程

目标

让 Tianole 从只运行 kernel 代码,进入可运行用户程序的阶段。

前置条件

  • 虚拟内存可用。
  • VFS 可读取 ELF 文件或 init 程序。
  • 异常和 syscall 入口可用。

建议边界

  • kernel/syscall/:系统调用入口和分发。
  • kernel/process/:进程、线程、地址空间。
  • kernel/elf/:用户 ELF 加载。
  • arch/x86/ring 3 切换和 syscall 指令支持。

实现内容

  • 建立用户地址空间。
  • 建立 syscall ABI。
  • 建立用户指针检查。
  • 加载用户 ELF。
  • 支持进程退出和等待。
  • 早期可先实现 spawn/exit/wait,再演进到 fork/exec
  • 为 POSIX syscall、fcntl/stat/chmod、signal、pipe、socket、eventfd、futex、共享内存、poll/select 和 IPC 预留 ABI 边界。
  • 为 uid/gid、用户/组、文件权限、进程权限、capability 或等价隔离模型预留进程凭据结构。

1. User address space

  • 每个进程需要独立地址空间,内核映射和用户映射边界清楚。
  • 用户页权限必须区分 user/supervisor、read/write、execute。
  • 进程退出时必须释放用户页、页表页、VFS 引用和其他资源。
  • 后续 fork、COW、mmap 和 shared memory 要能接入同一地址空间模型。

2. Syscall ABI

  • 定义 syscall number、参数寄存器、返回值、错误码和 clobber 规则。
  • syscall 表要稳定记录,不能由 demo 程序和 kernel 临时约定。
  • syscall handler 必须复制和检查用户指针,不能直接解引用用户地址。
  • syscall 返回边界要能和调度、signal、进程退出共享。

3. Process/thread model

  • 区分进程、线程、地址空间、内核调度线程和打开文件表。
  • 早期可以一个进程一个线程,但结构不能排斥多线程。
  • 建立 pid、父子关系、退出码、wait 状态和 zombie 回收。
  • 后续 fork/exec/wait、线程、signal 和 job control 要有可扩展空间。

4. ELF loader

  • ELF loader 只负责校验和映射 ELF不负责文件系统路径策略。
  • 检查 ELF header、program header、segment 权限、对齐、入口地址和用户地址范围。
  • 加载器要建立用户栈、argc/argv/envp 或最小等价启动约定。
  • 非法 ELF 必须返回错误,不能 panic。

5. Fault and signal boundary

  • 用户态 page fault、invalid opcode、general protection 等异常应终止当前进程或转成后续 signal。
  • kernel fault 和 user fault 策略必须分开。
  • 预留 signal、kill、wait status 和 core dump/debug 信息。
  • 用户态崩溃不能破坏内核调度器、VFS 或其他进程。

Linux 参考原则

  • 参考 Linux task/mm/files 分离:调度实体、地址空间和文件表不是同一个对象。
  • 参考 Linux syscall ABIsyscall number 和参数规则稳定libc 可以独立绑定。
  • 参考 Linux ELF loaderVFS 提供文件loader 校验 program header 并建立用户映射。
  • 参考 Linux user access helpers所有用户指针都要复制/检查,不能直接信任。
  • 参考 Linux wait/exit/zombie 模型:进程退出和资源释放分阶段完成。

非玩具化约束

  • syscall 表要稳定记录。
  • 用户指针不能直接信任。
  • 进程、线程、地址空间结构不要混成一个对象。
  • 用户态崩溃不能直接拖垮 kernel。
  • syscall 不能只按当前 demo 程序硬编码。
  • 进程资源释放必须有明确所有权和引用计数规则。
  • fork/exec/wait、signal、pipe、poll/select 是运行复杂 Unix 程序的关键路径,不能被路线遗漏。
  • 用户态入口和 syscall 返回必须经过明确的 arch 边界。
  • ELF loader 不能把文件系统、权限和地址空间策略混在一个函数里。
  • 用户栈布局要文档化,不能靠某个 demo 程序猜测。
  • errno/错误码语义要能被 libc 映射。
  • 进程退出不能泄漏页表、VFS file、cwd、argv/envp 或 wait 状态。

验收方式

  • 最小用户程序可以输出并退出。
  • kernel 能回收用户进程资源。
  • 非法用户访问能进入异常处理并终止进程。
  • syscall ABI 文档化,后续可以被 libc 绑定。
  • 非法 syscall number 返回明确错误。
  • 用户指针越界不会导致 kernel panic。
  • ELF 错误输入有测试,返回加载失败。
  • 父进程能 wait 到子进程退出码。
  • 用户态进程反复启动和退出后,内存和 file 引用不会持续增长。

当前状态

未开始。

进入本阶段前,03-memory.md 需要支持用户地址空间基础,06-storage-vfs.md 需要能读取 ELF 或 init 程序。

后续扩展

  • fork/exec/wait
  • signal。
  • pipe。
  • shared memory。
  • futex。
  • poll/select。
  • uid/gid、权限和 capability。
  • 动态链接。
  • ptrace 或基础调试接口。