“Welcome to linux-0.11-rs.” 当这句欢迎语出现在串口终端时,你已经进入了一个用 Rust 从头构建的 1991 年风格 Linux 内核。没有宏内核的沉重历史包袱,也没有 C 语言里那些随时可能踩进陷阱的指针,这次,老内核换了一身内存安全的马甲,直接在 QEMU 里拉着一个完整的用户态跑了起来。
这个叫 linux-0.11-rs 的项目,摆明了就是一场技术考古式的重写实验。它把 Linus Torvalds 当年那版经典代码全部打散,用现代 Rust 的习语重建,同时死死咬住原版的行为语义——该有的进程管理、按需调页、写时复制 fork,一个没少;但模块边界干净得像刀切豆腐,类型系统把能犯的错在编译期就掐死在摇篮里。最狠的是,它不只让内核跑起来,还自带工具链,一条命令就能吐出带用户程序的磁盘镜像,按 `make run` 直接见 Shell。
接下来就逐一拆解这个“老酒新瓶”的项目,看看 Rust 到底给 Linux 0.11 注入了什么奇怪的能量——有些地方甚至能让你忘记这内核来自 35 年前。
内核功能完整度:进程、虚拟内存、Minix 文件系统,一个不落。linux-0.11-rs 照搬了原版 Linux 0.11 几乎所有的关键机制:完整的进程模型、基于按需调页和写时复制 fork 的虚拟内存、Minix v1 文件系统、ATA 硬盘驱动、VGA 加 PS/2 控制台、8250 串口控制台、TTY 层、信号处理,以及全部系统调用表。注意到那个 Minix v1 文件系统没有?连当年 OS 课程必考题都原样保留,古早味儿拉满。但所有实现都被塞进了 Rust 的强类型框架,指针解引用变成了 `Option` 和 `Result` 的组合,原来在 C 里极易出现的越界、释放后重用问题,在这里被编译器的借用检查堵得严严实实。一次重写,实际上等于给老内核做了一次全面的安全漏洞大扫除。
Rust 风格的“std”用户库:写应用就像写普通 Rust。这个项目没有让你在用户程序里手搓 `int 0x80` 那样的系统调用陷阱,而是提供了一个叫 `user_lib` 的库,它的公开接口直接镜像了标准库 `std` 的 `fs`、`io`、`path`、`env`、`process`、`time` 这些模块。结果就是,用户程序写起来跟正常的 Rust 程序几乎一模一样,`File::open`、`read_to_string`、`Command::new` 该咋用咋用,根本感受不到底下是一个手撸的操作系统内核。这种抽象方式不仅把系统调用胶水代码彻底藏起来,还让所有示例程序保持很高的可读性,对想要学习操作系统原理的开发者简直不要太友好。
手写 Shell 附带 80+ 个命令,管道、函数、补全都有。如果说内核是骨架,那么用户空间就是肌肉。linux-0.11-rs 的用户态塞进了一套手写的 POSIX 子集 Shell,以及超过 80 个 coreutils 工具。Shell 本身支持管道、控制流(if、for、while)、函数定义、glob 通配符、命令替换和算术替换。就连交互式行编辑器也做了 Tab 补全和命令历史,通过键盘上下键就能翻旧命令。试着在 Shell 里敲 `echo $((1 + 2 * 3))`,它会老老实实输出 7;定义一个递归阶乘函数 `fact() { if [ $1 -le 1 ]; then echo 1; else echo $(($1 * $(fact $(($1-1))))); fi; }`,然后运行 `fact 7`,终端吐出的 5040 赫然在目。这种完成度,已经超过许多教学内核的玩具级用户态,逼近一个轻量级开发环境的雏形。
一键镜像构建、独立工具 crate、开箱即用的容器环境。开发者显然不想让你折腾环境。仓库里 `tools/build-disk.sh` 这个脚本负责把全部用户程序编译好,按照 Unix 风格在镜像里铺出 `/etc`、`/dev`、`/bin` 目录,最后打包成可启动的磁盘镜像——一条命令直出,省去了到处找交叉编译链的噩梦。另外,`mbrkit` 和 `miniximg` 两个独立 crate 也被拆了出来,就算你只是想给自己的其他项目生成 MBR 或 Minix v1 镜像,也能直接拿去用。更贴心的是,仓库自带 devcontainer 配置,Clone 下来在 VS Code 里点一下“在容器中重新打开”,所有依赖就自动装好,直接 `make run` 就能看到内核启动。
端到端测试驱动引导:Shell 功能也可以用脚本验证。项目没有止步于“能跑就行”,而是构造了一套基于 QEMU 串口驱动的自动测试系统。测试用例写成 `.ktest` 脚本,放在 `ktest/suites/` 下,从启动内核到发送命令、检查回显,全部自动化。运行 `tools/run-tests.sh` 就能跑全套;也可以单独揪出 Shell 相关的测试集,或者只跑某一条用例。如果想节省启动时间,还能加上 `--disable-reboot` 让多个测试共享一个 QEMU 实例。这种测试思路让内核的调试不再依赖肉眼刷屏幕,也让该项目有了一丝“持续集成”的工业味,而不是又一篇随手抛出的 Gist。
归根结底,linux-0.11-rs 是一个极其诚实的教学项目。它没有声称自己更快、更现代,甚至没有试图替换成 ext2 或改用 VirtIO 驱动,而是用 Rust 的语言能力严格复现一段经典技术史。当你在 QEMU 里按下 `ls /bin | wc -l` 看到 69 这个数字时,会突然意识到:能让 1991 年的内核稳稳站在现代工具链之上,这件事本身就已经足够有吸引力了。
热门跟贴