# simplelinux **Repository Path**: aiworkstep/simplelinux ## Basic Information - **Project Name**: simplelinux - **Description**: main分支是默认分支 - **Primary Language**: Rust - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-20 - **Last Updated**: 2026-09-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SimpleLinux —— 教学型简易 Linux 内核 > 目标:实现一个简易版的类 Linux 操作系统,涵盖 **内存、进程、线程、虚拟文件系统、驱动、内核态、用户态、网络栈** 几大核心功能,帮助理解与掌握操作系统的核心实现思路。 这是一个用 **Rust(`no_std`)** 编写的 x86_64 教学内核。它不追求性能与完备,而是用最短、最朴素的实现把每一个 OS 概念讲清楚:每一层都能独立观测、独立验证。 --- ## 一、环境前置 | 项目 | 要求 | | --- | --- | | Rust 工具链 | `nightly`(由 `rust-toolchain.toml` 锁定,自动下载),组件含 `rust-src`、`llvm-tools`,target `x86_64-unknown-none` | | Cargo | 需 nightly 以启用 `bindeps`(artifact-dependencies,见 `.cargo/config.toml`) | | QEMU | `qemu-system-x86_64`(本仓库在 QEMU 10.0.13 上验证) | | Python 3 | 用于 `tools/` 下的用户态 ELF / initrd 生成脚本 | ## 二、快速开始 ```bash # 构建内核 + 生成可引导 BIOS 镜像(root runner 通过 bindeps 编译 kernel) make build # 等价于 cargo build -p simplelinux # 构建并拉起 QEMU(串口直连 stdio) make run # 等价于 cargo run -p simplelinux make release # 优化版 make debug # 附带 -s -S(GDB 桩,localhost:1234) make initrd # 重新生成 initrd(ustar) make clean ``` > ⚠️ 只能用 `cargo build/run -p simplelinux`(root runner)。直接对 `kernel` 打包会触发 `_start` 重复符号——`bootloader 0.11` 由 runner 统一链接。 手动抓串口(判定各 Phase 输出时更稳): ```bash IMG=$(find target -name "bios.img" | head -1) timeout 25 qemu-system-x86_64 -drive format=raw,file=$IMG -m 128M \ -serial file:/tmp/serial.log -display none -no-reboot \ -netdev user,id=n0 -device e1000,netdev=n0 cat /tmp/serial.log # 退出码 124 属 timeout 正常结束 ``` ## 三、功能地图(按 Phase) 内核在 `kernel_main` 中顺序执行各 Phase 的自检 demo,全部输出到串口。任一环节 `panic` 即说明该层被破坏。 | Phase | 功能点 | 关键模块 | 预期观测 | | --- | --- | --- | --- | | 0.5 | 引导 + 串口/VGA | `main.rs`、`serial.rs`、`vga.rs` | 启动横幅、`Hello` 双通道输出 | | 1 | 内存:GDT/IDT/中断/堆分配 | `gdt`、`interrupts`、`memory` | 堆分配成功、断点/缺页异常被捕获 | | 2 | 进程与上下文切换 | `process/task`、`arch/switch` | 多任务往返切换计数递增 | | 3 | 调度器(抢占/睡眠) | `process/scheduler` | 时间片轮转、`sleep` 到期唤醒 | | 4 | 内核任务 + 键盘/空闲交错 | `process`、`drivers/keyboard` | `ps` 快照含 ready/running/blocked/zombie | | 5 | 虚拟文件系统(VFS) | `fs/vfs`、`fs`、`devfs` | 挂载、`ls`/`cat`、fd 表读写 | | 6 | 用户态 ring3 + syscall | `arch/syscall_asm`、`syscall`、`user/` | `int 0x80` 进入内核执行 `write`/`exit` | | 7 | e1000 驱动 | `drivers/e1000` | RX/TX 环初始化、设备识别(见下方限制) | | 8 | 网络栈 + Shell | `net/*`、`shell.rs` | 各层校验和自洽、socket 经 VFS 读写、shell 内置命令全跑通 | 网络栈自底向上分层:`ethernet → arp → ip → icmp/udp/tcp → socket`,并通过 `SocketInode` 融入 VFS(“网络也是文件”)。Shell 作为内核任务运行,读取 `/dev/kbd`,`selftest::network()` 用 `keyboard::inject_str` 注入脚本化会话演示 `help/echo/ls/cat/ps/free/ifconfig/arp/netstat/ping` 等内置命令。 ## 四、架构分层地图(新手先看这里) 整个内核是一条**自底向上、依赖单向**的分层栈。记住这张图,就拥有了对整个工程的“上帝视角”: ``` L0 arch 唯一的裸汇编层:__switch / int 0x80 入口(其余模块零 asm) L1 启动/控制台 serial vga gdt interrupts timer L2 memory pmm(物理帧) → vmm(页表) → heap(内核堆) L3 process task scheduler elf (依赖 L2 + arch::switch) L4 syscall ring0↔ring3 边界 + sys_* (依赖 arch::syscall_asm, L3, gdt) L5 fs vfs → devfs/procfs/initrd (依赖 L2/L3) L6 drivers keyboard e1000/{init,rx,tx} (依赖 L2,经 /dev 暴露) L7 net ethernet→arp→ip→icmp→udp→tcp→socket (依赖 L6 + L5 SocketInode) L8 shell 经 syscall/VFS 消费上面全部 ────────────────────────────────────────────── selftest 各 Phase 的开机自检/演示(把“如何证明它 work”与 OS 结构分离) ``` **三条贯穿主线**(读懂它们就抓住了设计骨架): 1. **每个子系统只暴露一个 `init()`**,`kernel_main` 按依赖顺序逐个点亮:`serial → gdt/interrupts → memory → process/timer → syscall → fs → e1000 → net`。想理解启动,只需读 `main.rs` 这一条装配线(真正的初始化与 `selftest::*` 演示各居其位)。 2. **一切皆文件**:键盘 = `/dev/kbd`、进程/内存信息 = `/proc/*`、网络端点 = `SocketInode`——都被同一张 VFS + fd 表统一,`read/write` 系统调用对所有后端走同一条路径。 3. **Rust 在上、汇编只在 `arch/`**:非安全代码被隔离到唯一的最低层,语言栈分层清晰。 > 用户态 ELF 不在 Rust 里编译:`tools/gen_*.py` 手工生成 `user/*.elf` → `main.rs`/`selftest` 以 `include_bytes!` 内嵌 → 由 `process/elf.rs` 装载进 ring3。 > 📐 更完整的**多视图架构图集**(元结构类图 / 分层 DAG / 软硬件部署 / 系统调用时序 / 任务状态机 / 网络 RX 流水线 / 启动串行流程 / 内存页表装配,共 8 个视图、9 个 Mermaid 图块)见 **[docs/架构图.md](docs/架构图.md)**。 ## 五、目录结构 ``` simplelinux/ # workspace root,同时是 host runner(build.rs 产镜像 + 拉 QEMU) ├── kernel/ # no_std 内核 │ └── src/ │ ├── main.rs # 入口:kernel_main 子系统装配线(各 Phase demo 见 selftest/) │ ├── arch/ # L0 唯一的裸汇编层:switch.rs(__switch) · syscall_asm.rs(int 0x80/iretq) │ ├── serial.rs vga.rs gdt.rs interrupts.rs timer.rs # L1 控制台与 CPU 基础 │ ├── memory/ # L2 pmm/vmm/heap │ ├── process/ # L3 task/scheduler/elf(上下文切换汇编已下沉到 arch/) │ ├── syscall/ # L4 ring3 + int 0x80 分发(汇编见 arch/syscall_asm) │ ├── fs/ # L5 vfs/devfs/procfs/initrd │ ├── drivers/ # L6 keyboard、e1000/{mod,init,rx,tx,arp} │ ├── net/ # L7 ethernet/arp/ip/icmp/udp/tcp/socket │ ├── shell.rs # L8 内核 shell │ └── selftest/ # 各 Phase 开机自检/演示(mem/sched/fs/user/driver/net) ├── user/ # ring3 用户程序(tools/*.py 生成的 ELF 产物) ├── tools/ # gen_hello_elf.py / gen_vfs_elf.py / make_initrd.py ├── src/main.rs # runner:拼 BIOS 镜像并 exec QEMU ├── build.rs Cargo.toml Makefile rust-toolchain.toml .cargo/config.toml ├── docs/ # 操作手册.md、开发历程.md、架构图.md └── tests/ # 预留 ``` ## 六、测试脚本 | 脚本 | 作用 | 运行 | | --- | --- | --- | | `tools/gen_hello_elf.py` | 手写 x86-64 `hello` 用户 ELF(`write`+`exit`),`include_bytes!` 内嵌 | `python3 tools/gen_hello_elf.py` | | `tools/gen_vfs_elf.py` | 生成带 VFS 读写的用户 ELF | `python3 tools/gen_vfs_elf.py` | | `tools/make_initrd.py` | 打包 initrd(ustar 归档) | `make initrd` | 各 Phase 的“测试用例”即为其串口自检 demo:判定方式为运行后在串口日志中核对预期输出行、且全程无 `panic!` / Double Fault / 三方故障。 ## 七、已知限制 - **e1000 TX(QEMU 10.0.13)**:出站帧字节级构造正确,但设备模型不置 `ICR.TXQE` 完成位、host 侧 `pcap` 恒 0 包,属 emulator 级限制。故 Phase 8 网络验证采用“**注入合成入站帧 → 驱动 decode/构造/应答**”的确定性内部自洽校验,host 侧 `ping`/`nc` 不可观测。 - **教学范围裁剪**:不做 SMP、COW、信号、ext2、swap;算法一律取最朴素实现。 - **代码约束**:每个 `.rs ≤ 400 行`、每函数 `≤ 60 行`,用 Rust 类型系统表达 OS 概念。 ## 八、详细文档 仓库内 `docs/` 随仓库分发三份文档: - **[docs/操作手册.md](docs/操作手册.md)** —— 面向使用/测试:各功能点的前置条件、运行步骤、测试用例、预期效果与排障表。 - **[docs/开发历程.md](docs/开发历程.md)** —— 面向考古/贡献:从目标到 Phase 8 的探索过程、架构取舍与关键踩坑史。 - **[docs/架构图.md](docs/架构图.md)** —— 面向结构理解:按真实代码绘制的 8 视图 Mermaid 多视图 DAG(元结构/组合/分层/软硬件/时序/并发/启动/内存)。 (在 IDE 中亦可通过 RepoWiki / 知识库查看同名《操作手册》。) ## 九、版本管理 按 Phase 分阶段提交并推送;每个 Phase 完成即做一次 `feat(...)` 提交。当前主线:`6baf059` 初始化 → `2e3c1c8` Phase 8(网络栈 + VFS socket + 交互式 shell)。