Every operating system starts as a small program that does almost nothing. Over time, it gains the ability to manage memory, run programs, and store files. In this guide, we will start from an empty computer and build up those abilities one step at a time.
This guide is structured into chapters. Each chapter will adds a new layer to our kernel, expanding its capabilities. While it isn't necessary to follow the chapters in order later chapters might reference earlier ones.
At its simplest an operating system is a software that manages hardware resources.
It's responsible for:
- Process management: Deciding which programs run and when
- Memory management: Keeping that of whats stored where and ensures that programs don't step on eachothers data.
- Device I/O: Talking the hardware like disks, keyboards and screens.
- Filesystems: Organsizing persistent data so it can be stored and retrieved.
- User interfaces: Enabling humans (and sometimes other machines) to interact with the system.
A typical OS has distinct layers each with their own responsibilities:
- Bootloader: The minimal code which runs first on power-on (after the BIOS), responsible for loading a kernel from disk into memory
- Kernel: The heart of the OS managing processes, memory and devices.
- Drivers: Software which talks directly to hardware.
- Libraries: Common code used by applications.
- Userspace: Applications and interfaces running on top of the kernel.
When writing an OS you will benefit from experience in:
- A systems programming language like Rust, C or C++.
- Low-level memory concepts such as memory addressing, pointers and bitwise operations.
- Simple computer architecture such as how the CPU executes instructions and how memory is structured.
- How a toolchain work with linkers and compilers.
Here is the broad roadmap we will follow:
- Building a freestanding kernel
- Booting using Limine
- Terminal output
- Loading a GDT
- Loading an IDT
- Building a PIC8259 driver
- Physical memory
- Paging
- Virtual memory
- Heap allocations