What is this?
This is a blog about building a real operating system from the ground up.
Not a toy that prints colored text to VGA and calls it a day. Not a tutorial that stops after you get a blinking cursor in Protected Mode. We are talking about a kernel that manages physical and virtual memory with multiple allocator strategies, preemptively schedules processes across isolated address spaces, mounts file systems, loads ELF binaries into userspace, and runs a graphical shell. A kernel in which we got Doom running.
AlkOS is a monolithic, general-purpose operating system kernel targeting x86-64, written in C++ (C++23 for the kernel, C17 for the standard library). It was developed from scratch over the course of a year by three students - Jakub Lisowski, Adam Ogieniewski, and Lukasz Kryczka - and documented in a BSc thesis at the Warsaw University of Technology.
This blog series takes everything we learned - the theory, the design decisions, the dead ends, the hard-won insights - and presents it as a structured guide for anyone who wants to understand how operating systems actually work, or build one themselves.
Why another OS dev blog?
If you have ever searched for OS development resources, you know the landscape. The OSDev Wiki is indispensable but uneven - some articles are brilliant, others are outdated or half-finished. Philipp Oppermann’s Writing an OS in Rust is excellent, but it covers the Rust ecosystem and stops before the system gets truly complex. Textbooks like Tanenbaum’s Modern Operating Systems explain theory well but leave a canyon between concept and implementation.
The real problem is what happens after the basics. You have a kernel that boots, prints to the screen, handles interrupts. Now what? How do you actually go from there to a system that runs programs? The resources for that journey are scarce because so few people complete it. The OSDev Wiki lists roughly 175 active hobbyist kernel projects. The number that make it to a functional userspace with process isolation is far smaller.
We made it to the other side. This blog is the guide we wish we had.
Contents
Here is what we will cover, roughly following the architecture of the system itself:
Foundation
- Development environment - cross-compilation toolchains, CMake build systems for bare-metal targets, QEMU emulation, and the freestanding vs. hosted compilation model
- Standard library - why you need your own libc (and libk), the CRT initialization sequence, and what it takes to make
printfwork without an OS underneath - Bootloading - the chain of trust from power-on to kernel entry, firmware abstraction, and the OS-level trampoline that bridges the bootloader’s normalized state to your kernel’s requirements
Memory
- Physical memory management - memory discovery, bitmap allocators, the Buddy System, TLSF (Two-Level Segregated Fit) for real-time allocation, and slab allocators for kernel object caching
- Virtual memory - multi-level page tables on x86-64, higher-half kernel mapping, demand paging, copy-on-write, VM areas, and the page fault handler that ties it all together
Hardware
- Interrupts and exceptions - the GDT, IDT, PIC vs. APIC/IOAPIC, interrupt frame design, and the subtle ways interrupt handling goes wrong
- Timing - TSC, HPET, LAPIC Timer, RTC, and building a high-precision timing subsystem that the scheduler can actually rely on
- ACPI and device discovery - integrating uACPI, enumerating PCI devices, and the surprisingly complex process of learning what hardware you are running on
Scheduling
- Process model - threads, processes, kernel workers, and the data structures that represent them
- The Meta-Scheduler - our tickless scheduling architecture, why we chose it over a traditional periodic tick, and how it orchestrates multiple scheduling policies (Round-Robin, Priority Queues, MLFQ) under a single abstraction
Userspace
- System call interface - designing the kernel-user boundary, our compile-time type-deducing dispatch table, and the transition from Ring 0 to Ring 3
- File systems - the VFS abstraction layer, our unified FAT12/16/32 driver, initrd, and file descriptor management
- ELF loading - parsing and loading ELF64 binaries into isolated address spaces
- The shell and graphics - framebuffer drivers, a window compositor, and running real programs in userspace
Each post will go deep. We will explain not just what we built, but why - what problem each component solves, what the alternatives were, what tradeoffs we made, and where we got it wrong. We will reference production kernels (Linux, MINIX 3) where their approaches informed ours, and academic papers where the theory matters.
Who is this for?
- People who want to build an OS. We will give you enough theory and enough implementation detail to actually do it. Not just the first 10%, but the full journey to a working userspace.
- Systems programmers who want to go deeper. Even if you never write a kernel, understanding what sits beneath your code makes you a better engineer. Memory allocators, scheduling algorithms, interrupt handling, virtual memory - this is the substrate everything runs on.
- Students and the curious. We documented this work as a thesis for a reason. OS development forces you to confront every layer of the stack simultaneously. There is no better way to understand how computers actually work.
The code
AlkOS is open source. The full kernel, userspace programs, build system, and toolchain configuration are available on GitHub. The posts in this series will reference specific source files and commit history. You can follow along, read the code, or use it as a starting point for your own project.
The project uses:
- C++23 for the kernel (with
-ffreestanding, no exceptions, no RTTI) - C17 for the standard library
- NASM for architecture-specific assembly
- CMake as the meta-build system
- GCC x86-64-elf cross-compiler
- QEMU for emulation and testing
Let’s begin
The next post starts where every OS starts: before you write a single line of kernel code. We will set up a cross-compilation toolchain, build a freestanding binary, and understand what it actually means to run code on a machine with no operating system.
See you there.