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

118 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 或基础调试接口。