# 操作系统设计综合实践 **Repository Path**: pan-yunyi/operating-system-design ## Basic Information - **Project Name**: 操作系统设计综合实践 - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-01 - **Last Updated**: 2026-09-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # operating-system-design 操作系统课程设计 —— 基于 XV6-RISC-V 的文件系统扩展与智能 Shell 增强(选题三) **核心功能:** - 扩展 XV6 文件系统:文件创建、删除、重命名、批量读写、目录遍历 - 增强 Shell:管道 `|`、输入输出重定向 `<` / `>`、后台运行 `&`、命令补全 - 简易文件权限机制:区分文件/目录读写权限,基础权限校验拦截 - `file_stat` 自定义系统调用:查询文件大小、修改时间、读写状态等信息 - 批量文件操作测试脚本,验证 Shell 与文件系统联动稳定性 **开发环境:** XV6-RISC-V、C 语言、QEMU、RISC-V 工具链、GDB --- ## 一、环境配置 > 配置一次即可。Linux 原生系统的安装方式与 Windows WSL 中完全相同,可参考 Windows 一节第 2 步。 ### macOS(约 15~30 分钟) **1. 安装 Homebrew(已装可跳过)** ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` 安装结束后按屏幕提示执行它给出的两行 `eval` 命令,把 brew 加入 PATH。 **2. 安装 QEMU 与 RISC-V 工具链** ```bash brew install qemu riscv64-elf-gcc riscv64-elf-gdb ``` **3. 建立工具前缀软链接** brew 安装的编译器前缀是 `riscv64-elf-`,而 XV6 的 Makefile 会自动寻找 `riscv64-unknown-elf-` 前缀的工具。用软链接解决,**不要修改 Makefile**(会影响其他平台的组员): ```bash mkdir -p ~/bin for t in gcc ld objdump objcopy ar gdb; do \ ln -sf "$(brew --prefix)/bin/riscv64-elf-$t" ~/bin/riscv64-unknown-elf-$t; done echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc source ~/.zshrc ``` **4. 验证安装** ```bash riscv64-unknown-elf-gcc --version # 能打印版本号即可 qemu-system-riscv64 --version ``` > 下载慢可先设置国内镜像: > ```bash > export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-bottles/api" > export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-bottles" > ``` ### Windows(使用 WSL2 + Ubuntu,推荐方式) 原生 Windows 编译 XV6 非常折腾,统一使用 WSL2 子系统。 **1. 安装 WSL2 和 Ubuntu** 以管理员身份打开 PowerShell 执行(全组统一用 Ubuntu 22.04),然后重启电脑: ```powershell wsl --install -d Ubuntu-22.04 ``` 重启后自动进入 Ubuntu,设置好用户名和密码(之后的 `sudo` 命令都用这个密码)。 **2. 在 Ubuntu 内安装工具链** ```bash sudo apt-get update && sudo apt-get install -y \ git build-essential gdb-multiarch qemu-system-misc \ gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu ``` `riscv64-linux-gnu-` 前缀能被 XV6 的 Makefile 自动识别,无需任何额外配置。 **3. 验证安装** ```bash riscv64-linux-gnu-gcc --version qemu-system-riscv64 --version ``` 若提示 `qemu-system-riscv64` 命令不存在,执行 `sudo apt install qemu-system` 后再验证。 **4. 两个重要注意事项** - 仓库必须 clone 在 WSL 的 Linux 目录下(如 `~/os/`),**不要**放在 `/mnt/c/...`(Windows 盘)下,否则编译速度极慢。 - clone 前先执行 `git config --global core.autocrlf input`,避免 Windows 换行符破坏 Makefile 和脚本。 --- ## 二、获取仓库源码 仓库地址:`https://gitee.com/pan-yunyi/operating-system-design.git` **第一次获取(还没 clone 过的人):** ```bash git clone https://gitee.com/pan-yunyi/operating-system-design.git cd operating-system-design ``` **已经 clone 过的人,每天开工先同步:** ```bash git pull origin main ``` > 如果 XV6 源码还没上传,clone 后仓库暂时只有文档;等上传后执行 `git pull origin main` 即可获取,无需重新 clone。 **推送规则:** - 推送前必须先 `git pull origin main`;若被拒绝(本地有新提交),使用 `git pull --rebase origin main` - **严禁 `git push -f` 强制推送**,会冲掉别人的提交 - 编译产物已被 `.gitignore` 排除,不要用 `git add -f` 强行添加 --- ## 三、编译与运行 进入仓库根目录(有 Makefile 的那一层): ```bash make qemu ``` 看到 `xv6 kernel is booting` 和 `$` 提示符即成功。 **退出 QEMU:先按 `Ctrl-a`,松开,再按 `x`。** --- ## 四、GDB 调试 **首次使用,每人做一次**(在仓库根目录执行,让 gdb 允许自动加载项目配置;这是 gdb 的安全机制,不配置会提示 auto-loading has been declined): ```bash echo "add-auto-load-safe-path $(pwd)" >> ~/.gdbinit ``` 之后日常是双终端: ```bash make qemu-gdb # 终端 1:QEMU 停在入口等待连接 ``` ```bash # 终端 2:仓库根目录下直接启动 gdb,自动连接并加载内核符号 riscv64-unknown-elf-gdb # macOS(环境配置章节建过软链接) riscv64-elf-gdb # macOS(brew 原名,二选一) gdb-multiarch # Windows WSL / Linux ``` > 调试配置由仓库模板 `.gdbinit.tmpl-riscv` 自动生成:每次 `make qemu-gdb` 都会按当前系统用户算出专属端口并写入本地 `.gdbinit`(此文件不提交,已加入 .gitignore),gdb 启动时自动连接并加载 `kernel/kernel` 符号;端口可用 `make print-gdbport` 查询。连上后 `pc` 停在 `0x1000`(QEMU 复位向量),连按几次 `si` 跳到内核入口 `_entry`(0x80000000),或直接 `b main` 后 `c`。 **常用命令:** ```text (gdb) b syscall # 下断点(如 b main、b scheduler、b usertrap) (gdb) c # 继续运行,断点处停下 (gdb) bt # 查看调用栈(停在用户态时无输出,属正常) (gdb) si / n # 单步一条指令 / 一行源码 (gdb) p cpus[$tp].proc->pid # 当前进程 pid($tp 是 hart 编号,不是指针) (gdb) p cpus[$tp].proc->name # 进程名 (gdb) p cpus[$tp].proc->trapframe->a7 # 系统调用号 (gdb) p/x $sstatus # bit8(SPP)=1 内核态陷入,0 用户态陷入 (gdb) info breakpoints / delete 1 # 查看 / 删除断点(看完现场及时删,见下) (gdb) info threads # Thread 1/2/3 对应三个 hart ``` > **多核提醒**:xv6 以 `-smp 3` 启动,三个 hart 都会执行 `main()`,所以 `b main` 这类断点会被连续命中三次(每次是不同的 hart)。在某 hart 的现场看完后,先 `delete 编号` 删掉断点再 `c`,否则会在下一个 hart 的 `main` 再次停下。 **三条纪律(都是踩过的坑):** 1. **退出时先 `kill` 再 `quit`**:直接 `quit` 只断开连接,QEMU 会留在后台,下次 `make qemu-gdb` 报 `Failed to get "write" lock`;遇到就 `pkill qemu-system-riscv64` 清理后重来。 2. **不要用 `p 函数名()`**(如 `p myproc()->pid`):gdb 会在当前特权级直接执行内核函数,停点在用户态时必然死锁;查进程信息一律用上面 `cpus[$tp]` 的写法(实测 `((struct cpu*)$tp)` 是错的——`$tp` 存的是 hart 编号而非指针)。 3. **系统调用参数看 trapframe,不看裸寄存器**:陷入时用户寄存器已由 trampoline 存入 `trapframe`,物理寄存器可能已被内核挪用(读 `trapframe->a0`、`trapframe->a7` 等)。 --- ## 五、小组协作规范 > 详细分工、文件所有权约定与三周里程碑见 [分工.md](分工.md)。 **按模块开分支,统一合并进 main,不要直接在 main 上开发**(分支名如 `feat/fs`、`feat/perm`、`feat/shell`、`feat/syscall`、`test`)。 **日常流程:** ```bash git pull origin main # 1. 开工先同步 git checkout -b feat/shell # 2. 切到自己的分支(首次创建) # ... 开发、小步提交 ... git push origin feat/shell # 3. 推送自己的分支 # 4. 每周由集成负责人(组员5)合并联调,或在 Gitee 上发 Pull Request ``` > `kernel/file.h`(dinode 结构)、`user/user.h`、`user/usys.pl`、`kernel/syscall.c`、`kernel/syscall.h` 几乎每个功能都要改,是冲突高发区;新增系统调用先在共享编号表登记,dinode 结构第一周定稿。 --- ## 六、常见问题与约定 ### 约定(防患于未然) 1. **编译报错先发群里确认**:macOS 与 Ubuntu 的交叉工具链版本不同,个别写法可能只在某个版本报错。确认是版本问题后,在 Makefile 加兼容选项,改动一次、提交推送、全队同步;严禁只在本地改了不提交。 2. **文件名统一小写,重命名不要只改大小写**:WSL 文件系统区分大小写而 macOS 不区分,只改大小写会导致一边正常一边混乱;确需修改用 `git mv` 分两步。 3. **所有文件保存为 UTF-8**:统一在 WSL / VS Code 内编辑,不要用 Windows 老编辑器(可能存成 GBK,别人打开是乱码)。 4. **不要在 Makefile、脚本、共享配置(.vscode 等)里写死自己平台专属的内容**(如 `riscv64-linux-gnu-` 前缀、`apt`、Windows 路径);工具链前缀 Makefile 会自动探测,共享调试配置需同时兼容 `riscv64-unknown-elf-gdb`(macOS)和 `gdb-multiarch`(WSL/Linux)。 ### Windows WSL 常见问题 - **睡眠唤醒后 make 疯狂重编译**:WSL 时钟漂移,在 WSL 里执行 `sudo hwclock -s` 修正,或 PowerShell 执行 `wsl --shutdown` 后重开。 - **编译奇慢**:仓库被放在了 `/mnt/c/` 下,移回 WSL 的 `~/`;工作副本全程只保留这一份。 - **WSL 内存占用过高**:创建 `C:\Users\<用户名>\.wslconfig`,写入 `[wsl2]` 和 `memory=4GB`,然后 `wsl --shutdown` 重启生效。 - **QEMU 退不出来、复制粘贴别扭**:改用 Windows Terminal 进入 WSL,不要用老的 cmd 窗口。 ### 排查思路 `git pull` 之后 `make qemu` 突然报错,优先怀疑最近一次提交:`git log --oneline -3` 和 `git diff` 看看刚合并了什么,重点检查 Makefile 和脚本里是否有人写死了平台专属内容;换行符问题已被 `.gitattributes` 根治,基本可以排除。