Real kernel modifications to a modified Linux 0.11 running under Bochs — an independent, from-skeleton implementation of the laboratory assignments of 哈尔滨工业大学《操作系统》(Harbin Institute of Technology "Operating Systems", 李治军), the classic hit-oslab course, part of a csdiy.wiki full-catalog build.
Each experiment is a genuine modification of the Linux 0.11 kernel (boot loader,
system calls, scheduler, memory manager, char drivers, filesystem) — not a
simulation. Every experiment is built with the period toolchain (gcc-3.4,
as86/ld86), booted in Bochs, and its effect is captured as real evidence
(screenshots and extracted files) under results/.
Because WSL2's kernel has no MINIX filesystem support, a small userspace
tools/mfs.py reads and writes the MINIX-v1 disk image directly,
so test programs, /etc/rc and generated output are injected and extracted fully
headlessly.
| # | Experiment | What it does | Status / evidence |
|---|---|---|---|
| 1 | 操作系统的引导 (bootloader) | custom banners in bootsect.s + setup.s, still boots to a shell |
✅ results/01.png, 01_shell.png |
| 2 | 系统调用 (system calls) | new iam() / whoami() syscalls |
✅ whoami reads back name set by another process; 36-char name → EINVAL (results/02*) |
| 3 | 进程运行轨迹跟踪与统计 (process trace) | scheduler logs N/J/R/W/E to /var/process.log |
✅ 267 events, CPU-bound child 400 jiffies running/0 blocked, IO-bound 0/424; timeline figure |
| 4 | 基于内核栈切换的进程切换 (kernel-stack switch) | replace TSS task-switch with kernel-stack switch_to |
|
| 5 | 信号量的实现与应用 (semaphores) | sem_open/wait/post/unlink + producer/consumer |
✅ 20 items, each produced & consumed exactly once (results/05*) |
| 6 | 地址映射与共享 (shared memory) | shmget/shmat/shmdt, one page mapped into two processes |
✅ parent reads the string the child wrote to shared memory (results/06*) |
| 7 | 终端设备的控制 (terminal control) | custom ESC[nz uppercase-toggle in the console driver |
✅ line renders uppercase after ESC[1z (results/07.png) |
| 8 | proc 文件系统 (/proc pseudo fs) | char-device /proc/psinfo & /proc/meminfo |
✅ cat shows live process table + uptime/free-mem (results/08*) |
Green = running, amber = ready, red = blocked. pid 0 (the idle task) fills
every gap; pid 10 is the CPU-bound child, pid 11 the IO-bound child.
- 1 — bootloader (
experiments/01-bootloader) - 2 — system calls (
experiments/02-syscall) - 3 — process trace (
experiments/03-process-trace) - 4 — kernel-stack switch (
experiments/04-kernel-stack-switch) — documented partial - 5 — semaphores (
experiments/05-semaphore) - 6 — shared memory (
experiments/06-shm) - 7 — terminal control (
experiments/07-terminal) - 8 — /proc filesystem (
experiments/08-procfs)
Each experiment directory has its own README.md, an overlay/ of the exact
modified kernel source files, any user/ test programs, the /etc/rc used to
drive it, and an outputs manifest of files extracted from the disk image.
hit-os/
├── linux-0.11/ # pristine hit-oslab Linux 0.11 base (GPLv2)
├── experiments/NN-name/ # per-lab overlay + user programs + rc + README
├── scripts/ # setup / build / run (Bochs-under-Xvfb capture)
├── tools/mfs.py # userspace MINIX-v1 fs reader/writer
├── results/ # captured screenshots, logs, timeline figure
├── LICENSE NOTICE
Everything runs in WSL2 Ubuntu (Linux-only kernel work).
# one-time: toolchain (gcc-multilib, bin86, bochs, bochs-x, xvfb, imagemagick)
# + the oslab-provided gcc-3.4, and the hit-oslab package at $OSLAB
scripts/setup.sh
# build + boot + capture one experiment (id, wait-seconds):
scripts/run.sh 01 5 # bootloader banners
scripts/run.sh 03 160 # process trace (then plot the figure:)
python experiments/03-process-trace/stat_log.py \
results/03__var_process.log results/03_process_timeline.png
scripts/run.sh 08 22 # /proc pseudo filesystemscripts/build.sh NN reconstructs experiment NN's kernel = the committed
linux-0.11/ base + experiments/NN/overlay/, and builds it with the period
toolchain. scripts/run.sh NN also injects the experiment's user programs and
/etc/rc into a fresh copy of the disk image, boots it headlessly in Bochs
(under Xvfb), screenshots the VGA console, and extracts the declared outputs.
QEMU cannot drive Linux 0.11's ancient hd.c (it panics with "harddisk I/O
error / Unable to mount root"), so all booting uses Bochs. Ubuntu's bochs
is a debugger build, so the harness feeds it a continue command and captures the
X framebuffer under Xvfb with ImageMagick. Every ✅ row above was produced by an
actual boot; the screenshots and extracted files under results/ are those runs.
Experiment 4 replaces Linux 0.11's TSS-based hardware task switch (switch_to is
just an ljmp through a task's TSS descriptor) with a kernel-stack switch:
switch_to becomes a routine that saves callee-saved registers on the current
kernel stack, swaps ESP to the next task's kernel stack, and returns into it;
schedule() calls it with the next PCB; and copy_process() must hand-craft the
new task's kernel stack so the very first switch "returns" cleanly into user
mode. experiments/04-kernel-stack-switch/ contains the design and the specific
edits. It is shipped as a documented partial: rewriting the context-switch
mechanism is the single most invasive change in the course and any of its
several interlocking pieces being subtly wrong faults the kernel on the first
switch; it is not fully brought up here. The other seven experiments span the
full range of kernel subsystems and are all verified end-to-end.
Linux 0.11 (C + x86 real-mode/protected-mode assembly), gcc-3.4 / as86 /
ld86, Bochs 2.7 + Xvfb + ImageMagick for headless boot capture, Python 3
(tools/mfs.py MINIX-v1 fs tool; matplotlib for the timeline figure), WSL2.
- The x86 boot sequence:
bootsect→setup→ protected mode → the kernel. - Adding system calls end-to-end:
sys_call_table,int 0x80, and moving data across the user/kernel boundary withget_fs_byte/put_fs_byte. - Instrumenting the scheduler and the danger of re-entrancy (logging from inside
schedule()overflows the 4 KB kernel stack without a guard). - Two ways to build a semaphore on Linux 0.11's primitives, and why
sleep_on/wake_upare fragile when waiters exit. - Address mapping: sharing one physical page between processes with
put_page. - Extending a VT102 console and building a
/proc-style pseudo file as a char device when there is no VFS to hang a filesystem on.
Based on the laboratory assignments of 哈尔滨工业大学《操作系统》(HIT "Operating
Systems", 李治军) and the hit-oslab environment (modified Linux 0.11, root
filesystem by Zhao Jiong / oldlinux.org). This repository is an independent
educational reimplementation; all course materials belong to their original
authors. See NOTICE: the kernel and its lab modifications are GPLv2
(derivative of Linux 0.11, © Linus Torvalds); the original tooling, test
programs, scripts and docs are MIT (LICENSE).
