Skip to content

rcore-os/tg-rcore-tutorial-ch7

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

第七章:进程间通信与信号

本章在第六章"文件系统"的基础上,引入了两大新机制:

  1. 管道(Pipe):基于文件描述符的进程间通信机制,用于父子进程之间的单向数据传递
  2. 信号(Signal):异步事件通知机制,允许一个进程向另一个进程发送事件通知

通过本章的学习和实践,你将理解:

  • 管道的概念、创建和使用流程
  • 管道的内部实现:环形缓冲区(Ring Buffer)
  • 统一的文件描述符抽象:文件、管道、标准 I/O 共享同一套接口
  • 信号的概念:信号集、信号屏蔽字、信号处理函数
  • 信号的发送(kill)、注册(sigaction)、屏蔽(sigprocmask)和返回(sigreturn)
  • 命令行参数的传递和 I/O 重定向的原理

前置知识:建议先完成第一章至第六章的学习,理解裸机启动、Trap 处理、系统调用、多任务调度、虚拟内存、进程管理和文件系统。

练习任务(以教代学,学以致用):

  • 学:读本文件,了解相关OS知识,在某个开发环境(在线或本地)中正确编译运行rcore-tutorial-ch7。
  • 教:分析并改进rcore-tutorial-ch7的文档和代码,让自己更高效地完成本章学习。
  • 用:基于rcore-tutorial-ch7的源代码,实现用户态简化版吃豆人游戏应用,还原经典玩法核心等基本功能;并扩展操作系统内核功能,支持用户态简化版吃豆人游戏应用。demo

注:与AI充分合作,并保存与AI合作的交互过程,总结如何做到与AI合作提升自己的操作系统知识与能力。

项目结构

ch7/
├── .cargo/
│   └── config.toml     # Cargo 配置:交叉编译目标和 QEMU runner
├── .gitignore           # Git 忽略规则
├── build.rs            # 构建脚本:编译用户程序,打包 easy-fs 磁盘镜像
├── Cargo.toml          # 项目配置与依赖
├── LICENSE             # GPL v3 许可证
├── README.md           # 本文档
├── rust-toolchain.toml # Rust 工具链配置
├── test.sh             # 自动测试脚本
└── src/
    ├── main.rs         # 内核主体:初始化、调度循环、系统调用实现(含信号处理)
    ├── fs.rs           # 文件系统管理 + 统一的 Fd 枚举
    ├── process.rs      # 进程结构:含 fd_table 和 signal
    ├── processor.rs    # 处理器管理:进程管理器
    └── virtio_block.rs # VirtIO 块设备驱动

源码阅读导航索引

返回根文档导航总表

本章建议按“统一 fd 抽象 -> 管道数据流 -> 信号状态机”三条线并行阅读。

阅读顺序 文件 重点问题
1 src/fs.rs 为什么要用 Fd 枚举统一文件/管道/标准 I/O?
2 src/main.rsimpls::IO pipereadwrite 如何共享同一套 fd_table 入口?
3 src/process.rs 进程信号状态在 from_elfforkexec 中如何继承/重置?
4 src/main.rs Trap 主循环 为什么在 syscall 返回前处理信号,处理结果如何影响进程存活?
5 src/main.rsimpls::Signal kill/sigaction/sigprocmask/sigreturn 的内核语义是什么?

配套建议:结合 tg-rcore-tutorial-signal / tg-rcore-tutorial-signal-impl 注释阅读,重点关注 handle_signals 的决策流程。

DoD 验收标准(本章完成判据)

  • 能解释为什么要用统一 Fd 枚举承载“文件/管道/标准IO”
  • 能从代码说明 pipe 建立后父子进程如何通过读写端通信
  • 能说明信号的发送、注册、屏蔽、返回四个关键 syscall 语义
  • 能解释“syscall 返回前检查信号”对进程退出路径的影响
  • 能执行 ./test.sh base 并通过本章基础测试

概念-源码-测试三联表

核心概念 源码入口 自测方式(命令/现象)
统一 fd 抽象 tg-rcore-tutorial-ch7/src/fs.rsFd 枚举 同一 read/write 入口可操作文件与管道
管道通信 tg-rcore-tutorial-ch7/src/main.rsimpls::IO::pipe 运行 tg-rcore-tutorial-ch7b_pipetest 可观察父子通信成功
信号状态管理 tg-rcore-tutorial-ch7/src/process.rssignal 字段与 fork 继承 子进程信号处理配置符合预期
信号 syscall tg-rcore-tutorial-ch7/src/main.rsimpls::Signal kill/sigaction/sigprocmask/sigreturn 行为正确

遇到构建/运行异常可先查看根文档的“高频错误速查表”。

一、环境准备

1.1 安装 Rust 工具链

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

验证:

rustc --version    # 要求 >= 1.85.0(支持 edition 2024)
cargo --version

1.2 添加 RISC-V 64 编译目标

rustup target add riscv64gc-unknown-none-elf

1.3 安装 QEMU 模拟器

Ubuntu / Debian:

sudo apt update
sudo apt install qemu-system-misc

macOS(Homebrew):

brew install qemu

验证:

qemu-system-riscv64 --version    # 建议 >= 7.0

1.4 安装额外工具

cargo install cargo-clone
cargo install cargo-binutils
rustup component add llvm-tools

1.5 获取源代码

方式一:只获取本实验

cargo clone tg-rcore-tutorial-ch7
cd tg-rcore-tutorial-ch7

方式二:获取所有实验

git clone --recurse-submodules https://github.com/rcore-os/tg-rcore-tutorial.git
cd tg-rcore-tutorial-ch7

二、编译与运行

2.1 编译

cargo build

构建过程与第六章相同:build.rs 会自动下载编译 tg-rcore-tutorial-user 用户程序,打包到 fs.img 磁盘镜像中。

环境变量说明:

  • TG_USER_DIR:指定本地 tg-rcore-tutorial-user 源码路径
  • TG_USER_VERSION:指定 tg-rcore-tutorial-user 版本(默认 0.2.0-preview.1
  • TG_SKIP_USER_APPS:跳过用户程序编译
  • LOG:设置日志级别

2.2 运行

cargo run

QEMU 命令与第六章相同(挂载 fs.img 块设备):

qemu-system-riscv64 \
    -machine virt \
    -nographic \
    -bios none \
    -drive file=target/riscv64gc-unknown-none-elf/debug/fs.img,if=none,format=raw,id=x0 \
    -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 \
    -kernel target/riscv64gc-unknown-none-elf/debug/tg-rcore-tutorial-ch7

2.3 预期输出

[tg-rcore-tutorial-ch7 ...] Hello, world!
[ INFO] .text    ---> 0x80200000..0x8023xxxx
[ INFO] .rodata  ---> 0x8023xxxx..0x8024xxxx
[ INFO] .data    ---> 0x8024xxxx..0x81exxxxx
[ INFO] .boot    ---> 0x81exxxxx..0x81exxxxx
[ INFO] (heap)   ---> 0x81exxxxx..0x83200000
[ INFO] MMIO range -> 0x10001000..0x10002000

Rust user shell
>> ch7b_pipetest
Read OK, child process exited!
pipetest passed!
Shell: Process 2 exited with code 0
>>

你可以在 Shell 中运行管道测试程序:

  • tg-rcore-tutorial-ch7b_pipetest:父进程通过管道向子进程传递字符串
  • tg-rcore-tutorial-ch7b_pipe_large_test:通过两个管道实现父子进程双向通信

2.4 运行测试

./test.sh           # 运行基础测试
./test.sh base      # 等价于上面
./test.sh all       # 运行全部测试(ch7 仅有基础测试)

三、操作系统核心概念

3.1 为什么需要进程间通信?

在前几章中,各个进程是完全独立的,它们无法直接交换数据。但在实际操作系统中,进程协作是非常常见的需求:

场景 说明
管道命令 cat file.txt | grep "hello" —— 前一个进程的输出作为后一个进程的输入
服务通信 Web 服务器将请求转发给后端处理进程
父子协作 父进程 fork 子进程后通过管道交换数据

管道 是最基本的 IPC 机制之一,它提供了一种简单的单向数据通道。

3.2 管道(Pipe)

管道的基本概念

管道是一对文件描述符:读端(read end)和写端(write end),数据从写端流向读端。

┌──────────┐     ┌──────────────────────────┐     ┌──────────┐
│ 父进程    │     │         管道              │     │ 子进程    │
│          │     │  ┌──────────────────────┐ │     │          │
│ write(fd) ──→  │  │   环形缓冲区          │ │  ──→ read(fd) │
│          │     │  │  [H|e|l|l|o|_|_|_|_] │ │     │          │
│          │     │  └──────────────────────┘ │     │          │
└──────────┘     └──────────────────────────┘     └──────────┘
    写端                                               读端

管道的创建和使用

典型的管道使用流程:

1. 父进程调用 pipe() 创建管道
   ┌─────────────────────┐
   │ fd_table:            │
   │   ...                │
   │   [3] = PipeRead     │  ← 读端
   │   [4] = PipeWrite    │  ← 写端
   └─────────────────────┘

2. 父进程调用 fork() 创建子进程
   父进程和子进程都拥有 fd[3](读端)和 fd[4](写端)

3. 子进程关闭写端 close(4),父进程关闭读端 close(3)
   父进程:write(4, "Hello")  →  管道  →  子进程:read(3, buf)

4. 通信完毕后,各自关闭剩余的 fd

管道的内部实现:环形缓冲区

管道内部使用环形缓冲区(Ring Buffer)存储数据:

PipeRingBuffer:
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ A │ B │ C │   │   │   │   │   │
└───┴───┴───┴───┴───┴───┴───┴───┘
  ↑head          ↑tail
  读取位置       写入位置

状态:
- EMPTY:head == tail 且已知为空
- FULL:head == tail 且已知为满
- NORMAL:其他情况

关键行为:

  • 读取(read):从 head 位置读取,head 向前移动。如果缓冲区为空,暂停当前进程等待数据。
  • 写入(write):向 tail 位置写入,tail 向前移动。如果缓冲区满,暂停当前进程等待读取。
  • 所有写端关闭:缓冲区中残余数据读完后,read 返回 0 表示 EOF。

pipe 系统调用

/// 创建管道
/// pipe: 用户空间的 usize[2] 数组地址
/// 返回:pipe[0] = 读端 fd,pipe[1] = 写端 fd
fn pipe(&self, pipe: usize) -> isize

3.3 统一的文件描述符类型(Fd 枚举)

本章引入了 Fd 枚举,将所有文件描述符类型统一管理:

pub enum Fd {
    File(FileHandle),           // 普通磁盘文件
    PipeRead(PipeReader),       // 管道读端
    PipeWrite(Arc<PipeWriter>), // 管道写端
    Empty { read, write },      // 空描述符(stdin/stdout/stderr)
}

统一接口的好处:

  • read/write 系统调用不需要知道 fd 的具体类型
  • 文件和管道可以混合使用(如 I/O 重定向)
  • fork 时子进程自动继承所有类型的 fd

3.4 信号(Signal)

信号的基本概念

信号是异步事件通知机制。进程可以在任意时刻收到信号,类似于硬件中断对 CPU 的打断。

常见信号:

信号 编号 默认行为 说明
SIGKILL 9 终止进程 不可捕获、不可忽略
SIGINT 2 终止进程 Ctrl+C
SIGTERM 15 终止进程 请求终止
SIGCHLD 17 忽略 子进程状态变化
SIGUSR1/2 10/12 终止进程 用户自定义

信号处理流程

进程 A                          进程 B
  │                               │
  │── kill(pid_B, SIGUSR1) ──→    │
  │                               │ (信号加入 received 位图)
  │                               │
  │                               │ ← syscall 返回前检查信号
  │                               │
  │                               │ 调用注册的信号处理函数
  │                               │ (或执行默认行为)
  │                               │
  │                               │ ← sigreturn 恢复原执行流

信号相关数据结构

每个进程的信号处理器(SignalImpl)维护:

pub struct SignalImpl {
    received: SignalSet,                        // 已接收的信号(位图)
    mask: SignalSet,                            // 信号屏蔽字(被屏蔽的信号不处理)
    handling: Option<HandlingSignal>,           // 正在处理的信号状态
    actions: [Option<SignalAction>; MAX_SIG+1], // 信号处理函数表
}

信号相关系统调用

系统调用 功能
kill(pid, signum) 向指定进程发送信号
sigaction(signum, action, old_action) 设置/获取信号处理函数
sigprocmask(mask) 更新信号屏蔽字
sigreturn() 从信号处理函数返回,恢复原上下文

信号处理时机

在本实现中,信号处理发生在系统调用返回用户态之前

// 系统调用执行完毕后
match task.signal.handle_signals(ctx) {
    SignalResult::ProcessKilled(exit_code) => {
        // 收到终止信号,进程退出
    },
    _ => {
        // 正常返回系统调用结果
    }
}

3.5 命令行参数与 I/O 重定向

虽然本 tg-rcore-tutorial-ch7 实现未完整支持命令行参数传递,但这是第七章教学内容的重要部分。

命令行参数

exec("program", ["arg1", "arg2"])

用户栈布局:
┌──────────────┐ 高地址
│ argv[0] 指针  │ → "program\0"
│ argv[1] 指针  │ → "arg1\0"
│ argv[2] 指针  │ → "arg2\0"
│ 0 (终止符)    │
├──────────────┤
│ "program\0"  │
│ "arg1\0"     │
│ "arg2\0"     │
├──────────────┤ ← user_sp(对齐到 8 字节)
│   ...        │
└──────────────┘ 低地址

进入用户态时,a0 = argc(参数个数),a1 = argv(参数数组指针)。

I/O 重定向

I/O 重定向通过文件描述符的"关闭-复制"技巧实现:

输出重定向:program > output.txt

1. fork() 创建子进程
2. 子进程中:
   fd = open("output.txt", CREATE|WRONLY)  // 假设 fd = 3
   close(1)                                 // 关闭 stdout
   dup(3)                                   // 复制 fd 3 → 得到 fd 1
   close(3)                                 // 关闭原始 fd
   exec("program")                          // 程序的 stdout 现在指向 output.txt

3.6 系统调用汇总

syscall ID 名称 功能 状态
59 pipe 创建管道 新增
129 kill 发送信号 新增
134 sigaction 设置信号处理 新增
135 sigprocmask 设置屏蔽字 新增
139 sigreturn 信号返回 新增
56 open 打开文件 继承
57 close 关闭 fd 继承
63 read 读取(扩展:支持管道) 扩展
64 write 写入(扩展:支持管道) 扩展
93 exit 退出进程 继承
220 fork 创建子进程(扩展:继承信号配置) 扩展
221 exec 替换程序 继承
260 wait 等待子进程 继承

四、代码解读

4.1 src/main.rs —— 内核主体

与第六章的区别:

  • 新增 tg_syscall::init_signal() 初始化信号系统调用
  • 主调度循环中,系统调用返回前新增信号处理
    • SignalResult::ProcessKilled:进程被终止信号杀死
    • 其他情况:正常处理系统调用返回值
  • impls 模块新增 Signal trait 实现(kill/sigaction/sigprocmask/sigreturn)
  • impls 模块新增 pipe 系统调用实现

4.2 src/fs.rs —— 文件系统管理 + Fd 枚举

核心变化:统一的 Fd 枚举

  • Fd::File(FileHandle):普通磁盘文件
  • Fd::PipeRead(PipeReader):管道读端
  • Fd::PipeWrite(Arc<PipeWriter>):管道写端
  • Fd::Empty { read, write }:空描述符(stdin/stdout/stderr)

所有类型都实现了 readable()writable()read()write() 方法。

4.3 src/process.rs —— 进程管理

与第六章的区别:

  • fd_table 类型从 Vec<Option<Mutex<FileHandle>>> 变为 Vec<Option<Mutex<Fd>>>
  • 新增 signal: Box<dyn Signal> 字段
  • fork() 通过 self.signal.from_fork() 让子进程继承信号配置
  • from_elf() 使用 Fd::Empty 初始化 stdin/stdout/stderr

4.4 Cargo.toml —— 依赖说明

与第六章相比新增的依赖:

依赖 说明
tg-rcore-tutorial-signal 信号模块 trait 定义(Signal、SignalResult、SignalNo)
tg-rcore-tutorial-signal-impl 信号模块参考实现(SignalImpl)

信号 crate 依赖关系:

tg-rcore-tutorial-ch7
  ├── tg-rcore-tutorial-signal-impl → tg-rcore-tutorial-signal → tg-rcore-tutorial-signal-defs → numeric-enum-macro
  ├── tg-rcore-tutorial-signal
  └── tg-rcore-tutorial-syscall → tg-rcore-tutorial-signal-defs

五、本章小结

通过本章的学习和实践,你完成了操作系统中进程间通信的核心机制:

  1. 管道机制:基于环形缓冲区的单向数据通道,通过 pipe 系统调用创建
  2. 统一文件描述符:Fd 枚举将文件、管道、标准 I/O 统一为一套接口
  3. 信号机制:异步事件通知,支持信号发送、处理函数注册、屏蔽和返回
  4. 命令行参数:通过用户栈传递参数给程序
  5. I/O 重定向:通过文件描述符的关闭-复制技巧实现

六、思考题

  1. 管道 vs 共享内存:管道通过内核缓冲区传递数据,而共享内存允许进程直接访问同一块物理内存。各有什么优缺点?什么场景下应该使用哪种?

  2. 管道的阻塞语义:当管道缓冲区为空时,读取操作应该阻塞等待。在本实现中,这种"阻塞"是如何实现的?(提示:任务切换)

  3. 信号 vs 管道:信号和管道都是 IPC 机制,但它们的适用场景有何不同?信号能传递数据吗?

  4. 信号处理时机:本实现中信号在系统调用返回前处理。如果进程正在执行用户态代码(没有系统调用),信号什么时候被处理?理想的实现应该是什么样的?

  5. fork 后的管道共享:fork 后父子进程共享管道的读端和写端。为什么通常需要在子进程中关闭不需要的一端?如果不关闭会有什么问题?

  6. 环形缓冲区的大小:管道的环形缓冲区大小是固定的。如果写入的数据量超过缓冲区大小会发生什么?Linux 中管道的默认缓冲区大小是多少?

参考资料


附录:rCore-Tutorial 组件分析表

表 1:tg-rcore-tutorial-ch1 ~ tg-rcore-tutorial-ch8 操作系统内核总体情况描述表

操作系统内核 所涉及核心知识点 主要完成功能 所依赖的组件
tg-rcore-tutorial-ch1 应用程序执行环境
裸机编程(Bare-metal)
SBI(Supervisor Binary Interface)
RISC-V 特权级(M/S-mode)
链接脚本(Linker Script)
内存布局(Memory Layout)
Panic 处理
最小 S-mode 裸机程序
QEMU 直接启动(无 OpenSBI)
打印 "Hello, world!" 并关机
演示最基本的 OS 执行环境
tg-rcore-tutorial-sbi
tg-rcore-tutorial-ch2 批处理系统(Batch Processing)
特权级切换(U-mode ↔ S-mode)
Trap 处理(ecall / 异常)
上下文保存与恢复
系统调用(write / exit)
用户态 / 内核态
sret 返回指令
批处理操作系统
顺序加载运行多个用户程序
特权级切换和 Trap 处理框架
实现 write / exit 系统调用
tg-rcore-tutorial-sbi
tg-rcore-tutorial-linker
tg-rcore-tutorial-console
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-syscall
tg-rcore-tutorial-ch3 多道程序(Multiprogramming)
任务控制块(TCB)
协作式调度(yield)
抢占式调度(Preemptive)
时钟中断(Clock Interrupt)
时间片轮转(Time Slice)
任务切换(Task Switch)
任务状态(Ready/Running/Finished)
clock_gettime 系统调用
多道程序与分时多任务
多程序同时驻留内存
协作式 + 抢占式调度
时钟中断与时间管理
tg-rcore-tutorial-sbi
tg-rcore-tutorial-linker
tg-rcore-tutorial-console
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-syscall
tg-rcore-tutorial-ch4 虚拟内存(Virtual Memory)
Sv39 三级页表(Page Table)
地址空间隔离(Address Space)
页表项(PTE)与标志位
地址转换(VA → PA)
异界传送门(MultislotPortal)
ELF 加载与解析
堆管理(sbrk)
恒等映射(Identity Mapping)
内存保护(Memory Protection)
satp CSR
引入 Sv39 虚拟内存
每个用户进程独立地址空间
跨地址空间上下文切换
进程隔离和内存保护
tg-rcore-tutorial-sbi
tg-rcore-tutorial-linker
tg-rcore-tutorial-console
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-kernel-alloc
tg-rcore-tutorial-kernel-vm
tg-rcore-tutorial-syscall
tg-rcore-tutorial-ch5 进程(Process)
进程控制块(PCB)
进程标识符(PID)
fork(地址空间深拷贝)
exec(程序替换)
waitpid(等待子进程)
进程树 / 父子关系
初始进程(initproc)
Shell 交互式命令行
进程生命周期(Ready/Running/Zombie)
步幅调度(Stride Scheduling)
引入进程管理
fork / exec / waitpid 系统调用
动态创建、替换、等待进程
Shell 交互式命令行
tg-rcore-tutorial-sbi
tg-rcore-tutorial-linker
tg-rcore-tutorial-console
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-kernel-alloc
tg-rcore-tutorial-kernel-vm
tg-rcore-tutorial-syscall
tg-rcore-tutorial-task-manage
tg-rcore-tutorial-ch6 文件系统(File System)
easy-fs 五层架构
SuperBlock / Inode / 位图
DiskInode(直接+间接索引)
目录项(DirEntry)
文件描述符表(fd_table)
文件句柄(FileHandle)
VirtIO 块设备驱动
MMIO(Memory-Mapped I/O)
块缓存(Block Cache)
硬链接(Hard Link)
open / close / read / write 系统调用
引入文件系统与 I/O
用户程序存储在磁盘镜像(fs.img)
VirtIO 块设备驱动
easy-fs 文件系统实现
文件打开 / 关闭 / 读写
tg-rcore-tutorial-sbi
tg-rcore-tutorial-linker
tg-rcore-tutorial-console
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-kernel-alloc
tg-rcore-tutorial-kernel-vm
tg-rcore-tutorial-syscall
tg-rcore-tutorial-task-manage
tg-rcore-tutorial-easy-fs
tg-rcore-tutorial-ch7 进程间通信(IPC)
管道(Pipe)
环形缓冲区(Ring Buffer)
统一文件描述符(Fd 枚举)
信号(Signal)
信号集(SignalSet)
信号屏蔽字(Signal Mask)
信号处理函数(Signal Handler)
kill / sigaction / sigprocmask / sigreturn
命令行参数(argc / argv)
I/O 重定向(dup)
进程间通信-管道
异步事件通知(信号)
统一文件描述符抽象
信号发送 / 注册 / 屏蔽 / 返回
tg-rcore-tutorial-sbi
tg-rcore-tutorial-linker
tg-rcore-tutorial-console
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-kernel-alloc
tg-rcore-tutorial-kernel-vm
tg-rcore-tutorial-syscall
tg-rcore-tutorial-task-manage
tg-rcore-tutorial-easy-fs
tg-rcore-tutorial-signal
tg-rcore-tutorial-signal-impl
tg-rcore-tutorial-ch8 同步互斥(Sync&Mutex)
线程(Thread)/ 线程标识符(TID)
进程-线程分离
竞态条件(Race Condition)
临界区(Critical Section)
互斥(Mutual Exclusion)
互斥锁(Mutex:自旋锁 vs 阻塞锁)
信号量(Semaphore:P/V 操作)
条件变量(Condvar)
管程(Monitor:Mesa 语义)
线程阻塞与唤醒(wait queue)
死锁(Deadlock)/ 死锁四条件
银行家算法(Banker's Algorithm)
双层管理器(PThreadManager)
进程-线程分离
同一进程内多线程并发
互斥锁(MutexBlocking)
信号量(Semaphore)
条件变量(Condvar)
线程阻塞与唤醒机制
死锁检测(练习)
tg-rcore-tutorial-sbi
tg-rcore-tutorial-linker
tg-rcore-tutorial-console
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-kernel-alloc
tg-rcore-tutorial-kernel-vm
tg-rcore-tutorial-syscall
tg-rcore-tutorial-task-manage
tg-rcore-tutorial-easy-fs
tg-rcore-tutorial-signal
tg-rcore-tutorial-signal-impl
tg-rcore-tutorial-sync

表 2:tg-rcore-tutorial-ch1 ~ tg-rcore-tutorial-ch8 操作系统内核所依赖组件总体情况描述表

功能组件 所涉及核心知识点 主要完成功能 所依赖的组件
tg-rcore-tutorial-sbi SBI(Supervisor Binary Interface)
console_putchar / console_getchar
系统关机(shutdown)
RISC-V 特权级(M/S-mode)
ecall 指令
S→M 模式的 SBI 调用封装
字符输出 / 字符读取
系统关机
支持 nobios 直接操作 UART
tg-rcore-tutorial-console 控制台 I/O
格式化输出(print! / println!)
日志系统(Log Level)
自旋锁保护的全局控制台
可定制 print! / println! 宏
log::Log 日志实现
Console trait 抽象底层输出
tg-rcore-tutorial-kernel-context 上下文(Context)
Trap 帧(Trap Frame)
寄存器保存与恢复
特权级切换
stvec / sepc / scause CSR
LocalContext(本地上下文)
ForeignContext(跨地址空间上下文)
异界传送门(MultislotPortal)
用户/内核态切换上下文管理
LocalContext 结构
ForeignContext(含 satp)
MultislotPortal 跨地址空间执行
tg-rcore-tutorial-kernel-alloc 内核堆分配器
伙伴系统(Buddy Allocation)
动态内存管理
#[global_allocator]
基于伙伴算法的 GlobalAlloc
堆初始化(init)
物理内存转移(transfer)
tg-rcore-tutorial-kernel-vm 虚拟内存管理
页表(Page Table)
Sv39 分页(三级页表)
虚拟地址(VAddr)/ 物理地址(PAddr)
虚拟页号(VPN)/ 物理页号(PPN)
页表项(PTE)/ 页表标志位(VmFlags)
地址空间(AddressSpace)
PageManager trait
地址翻译(translate)
Sv39 页表管理
AddressSpace 地址空间抽象
虚实地址转换
页面映射(map / map_extern)
页表项操作
tg-rcore-tutorial-syscall 系统调用(System Call)
系统调用号(SyscallId)
系统调用分发(handle)
系统调用结果(Done / Unsupported)
Caller 抽象
IO / Process / Scheduling / Clock /
Signal / Thread / SyncMutex trait 接口
系统调用 ID 与参数定义
trait 接口供内核实现
init_io / init_process / init_scheduling /
init_clock / init_signal /
init_thread / init_sync_mutex
支持 kernel / user feature
tg-rcore-tutorial-signal-defs
tg-rcore-tutorial-task-manage 任务管理(Task Management)
调度(Scheduling)
进程管理器(PManager, proc feature)
双层管理器(PThreadManager, thread feature)
ProcId / ThreadId
就绪队列(Ready Queue)
Manage trait / Schedule trait
进程等待(wait / waitpid)
线程等待(waittid)
阻塞与唤醒(blocked / re_enque)
Manage 和 Schedule trait 抽象
proc feature:单层进程管理器(PManager)
thread feature:双层管理器(PThreadManager)
进程树 / 父子关系
线程阻塞 / 唤醒
tg-rcore-tutorial-easy-fs 文件系统(File System)
SuperBlock / Inode / 位图(Bitmap)
DiskInode(直接+间接索引)
块缓存(Block Cache)
BlockDevice trait
文件句柄(FileHandle)
打开标志(OpenFlags)
管道(Pipe)/ 环形缓冲区
用户缓冲区(UserBuffer)
FSManager trait
easy-fs 五层架构实现
文件创建 / 读写 / 目录操作
块缓存管理
管道环形缓冲区实现
FSManager trait 抽象
tg-rcore-tutorial-signal-defs 信号编号(SignalNo)
SIGKILL / SIGINT / SIGUSR1 等
信号动作(SignalAction)
信号集(SignalSet)
最大信号数(MAX_SIG)
信号编号枚举定义
信号动作结构定义
信号集类型定义
为 tg-rcore-tutorial-signal 和 tg-rcore-tutorial-syscall 提供共用类型
tg-rcore-tutorial-signal 信号处理(Signal Handling)
Signal trait 接口
add_signal / handle_signals
get_action_ref / set_action
update_mask / sig_return / from_fork
SignalResult(Handled / ProcessKilled)
Signal trait 接口定义
信号添加 / 处理 / 动作设置
屏蔽字更新 / 信号返回
fork 继承
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-signal-defs
tg-rcore-tutorial-signal-impl SignalImpl 结构
已接收信号位图(received)
信号屏蔽字(mask)
信号处理中状态(handling)
信号动作表(actions)
信号处理函数调用
上下文保存与恢复
Signal trait 的参考实现
信号接收位图管理
屏蔽字逻辑
处理状态和动作表
tg-rcore-tutorial-kernel-context
tg-rcore-tutorial-signal
tg-rcore-tutorial-sync 互斥锁(Mutex trait: lock / unlock)
阻塞互斥锁(MutexBlocking)
信号量(Semaphore: up / down)
条件变量(Condvar: signal / wait_with_mutex)
等待队列(VecDeque<ThreadId>)
UPIntrFreeCell
MutexBlocking 阻塞互斥锁
Semaphore 信号量
Condvar 条件变量
通过 ThreadId 与调度器交互
tg-rcore-tutorial-task-manage
tg-rcore-tutorial-user 用户态程序(User-space App)
用户库(User Library)
系统调用封装(syscall wrapper)
用户堆分配器
用户态 print! / println!
用户测试程序运行时库
系统调用封装
用户堆分配器
各章节测试用例(ch2~ch8)
tg-rcore-tutorial-console
tg-rcore-tutorial-syscall
tg-rcore-tutorial-checker 测试验证
输出模式匹配
正则表达式(Regex)
测试用例判定
rCore-Tutorial CLI 测试输出检查工具
验证内核输出匹配预期模式
支持 --ch N 和 --exercise 模式
tg-rcore-tutorial-linker 链接脚本(Linker Script)
内核内存布局(KernelLayout)
.text / .rodata / .data / .bss / .boot 段
入口点(boot0! 宏)
BSS 段清零
形成内核空间布局的链接脚本模板
用于 build.rs 工具构建 linker.ld
内核布局定位(KernelLayout::locate)
入口宏(boot0!)
段信息迭代

License

Licensed under GNU GENERAL PUBLIC LICENSE, Version 3.0.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors