I recently published miniOS on GitHub, a hobby x86_64 kernel I’ve been poking at on and off for years. Docs are here if you want the technical deep-dive. But before miniOS was a kernel with SMP scheduling and a network stack, it was a small test harness I wrote during university to answer one specific question.
The question
Back then, Xenomai and RTLinux already existed, and both gave you hard real-time guarantees by running your time-critical code as a kernel task, next to (or underneath) a regular Linux kernel. That works, but it means your real-time code has to live in kernel space, with everything that implies for development, debugging, and safety.
Our project wanted something different: could you get hard real-time execution latency for code running as an ordinary userspace process, in ring 3, on unmodified-ish Linux?
The idea was to isolate one or more CPU cores away from the Linux scheduler entirely and let a single process own a core outright, no other tasks, no interrupts routed there if we could help it. I patched Linux to support that core isolation. If it worked, you’d get real-time behavior without ever leaving userspace.
Measuring against the hardware itself
To know whether “isolate a core and pin a process to it” actually got you anywhere close to hard real-time, we needed a baseline: what’s the best-case latency the x86 platform can physically deliver, with nothing in the way at all? No Linux, no scheduler, no interrupt subsystem you didn’t write yourself.
That’s what miniOS started as. A minimal harness that could boot on bare x86 hardware and run a benchmark payload with nothing else running on the core. We used the Hourglass benchmark methodology (Utah Flux group, USENIX 2002) to measure scheduling/execution latency, and ran the same benchmark on both:
- Linux, with our core-isolation patch, process pinned to an isolated core
- miniOS, running the payload directly on bare hardware
The real floor we were chasing was whatever latency the CPU’s System Management Mode (SMM) imposes — SMM interrupts are invisible to the OS and can steal cycles from anything, including a kernel with no other job than running one payload. So the miniOS number was as close as we could get to “the hardware’s own floor,” while still executing the actual application code in ring 3, the same privilege level a normal userspace process runs at.
Comparing the two told us how much latency was actually attributable to Linux’s own overhead (scheduler, interrupt handling, whatever we hadn’t managed to isolate away) versus the irreducible SMM cost that no amount of kernel patching could ever remove.
From benchmark harness to hobby kernel
The university project ended, but the harness stuck around. Over the years I kept extending it long after the original research question was answered, mostly because bare-metal x86 programming is just fun, and miniOS was a good excuse to learn how a real kernel is put together without the weight of an existing codebase.
It’s grown a lot since these days. Current miniOS has:
- SMP scheduling with per-CPU run queues and work stealing
- Real fork/exec via per-process page tables, with copy-on-write
- A POSIX-ish userspace on top of mlibc and BusyBox
- ext2, tmpfs, sysfs, fat32 and procfs over a GPT-partitioned disk with a cached block layer
- An lwIP-based network stack (virtio-net/RTL8139) with POSIX sockets and a userspace DNS resolver
- ptrace, job control, pthreads, futexes, Unix domain sockets
None of that was in the original benchmark harness — it’s what happens when a “just measure some latency numbers” tool becomes a long-running hobby project. I’m planning more posts on the low-level bits of systems programming, miniOS included, so consider this the origin story for whatever comes next.