Introduction: What is an Operating System?
Series Overview: This is Phase 0 of our 18-part Kernel Development Series. We'll build a complete operating system from scratch, covering boot processes, memory management, filesystems, processes, drivers, and more. By the end, you'll have a fully functional OS that you understand from the first instruction to the last pixel.
Imagine you just bought a brand new computer. You press the power button and... nothing useful happens. The CPU wakes up and starts executing instructions, but without software to orchestrate everything, your expensive hardware is just an expensive paperweight. The operating system (OS) is what transforms raw hardware into a usable computer.
Think of the operating system as the manager of a busy restaurant. The hardware is the kitchen equipment, the waitstaff, and the tables. Without a manager, the cooks would fight over who uses the stove, customers would seat themselves randomly, and orders would get lost. The manager (OS) coordinates everything: who uses which resource, when, and for how long.
1
Phase 0: Orientation & Big Picture
OS fundamentals, kernel architectures, learning path
You Are Here
2
Phase 1: How a Computer Starts
BIOS/UEFI, boot sequence, dev environment
3
Phase 2: Real Mode - First Steps
Real mode, bootloader, BIOS interrupts
4
Phase 3: Entering Protected Mode
GDT, 32-bit mode, C code execution
5
Phase 4: Display, Input & Output
VGA text mode, keyboard handling
6
Phase 5: Interrupts & CPU Control
IDT, ISRs, PIC programming
7
Phase 6: Memory Management
Paging, virtual memory, heap allocator
8
Phase 7: Disk Access & Filesystems
Block devices, FAT, VFS layer
9
Phase 8: Processes & User Mode
Task switching, system calls, user space
10
Phase 9: ELF Loading & Executables
ELF format, program loading
11
Phase 10: Standard Library & Shell
C library, command-line shell
12
Phase 11: 64-Bit Long Mode
x86-64, 64-bit paging, modern architecture
13
Phase 12: Modern Booting with UEFI
UEFI boot services, memory maps
14
Phase 13: Graphics & GUI Systems
Framebuffer, windowing, drawing
15
Phase 14: Advanced Input & Timing
Mouse, high-precision timers
16
Phase 15: Hardware Discovery & Drivers
PCI, device drivers, NVMe
17
Phase 16: Performance & Optimization
Caching, scheduler tuning
18
Phase 17: Stability, Security & Finishing
Debugging, hardening, completion
What Does an OS Actually Do?
An operating system has several core responsibilities:
Resource Management
- CPU Time - Deciding which program runs when
- Memory - Allocating RAM to programs safely
- Storage - Managing files and directories
- Devices - Coordinating access to hardware
Protection & Security
- Isolation - Programs can't interfere with each other
- Permissions - Controlling who can access what
- Hardware Protection - Preventing crashes from bad code
- Fairness - Ensuring no program hogs resources
Real-World Analogy: The Office Building
Conceptual Model
Imagine an office building (your computer). Each office (process) has workers (threads) doing tasks. The building has limited resources:
- Conference Rooms (CPU) - The OS schedules who uses them and for how long
- Filing Cabinets (RAM) - The OS assigns cabinet space to each office
- The Basement Archive (Disk) - The OS manages the filing system
- Building Entrance (I/O Devices) - The OS controls access to the outside world (network, printers)
The kernel is the building's management company - always running in the background, making sure everything works smoothly without tenants having to worry about the details.
Why Build Your Own Operating System?
Building an OS from scratch is one of the most educational projects a programmer can undertake. Here's why:
| Benefit |
What You'll Learn |
| Deep Hardware Understanding |
How CPUs actually execute code, memory hierarchies, device communication |
| Systems Programming Mastery |
Low-level C, assembly, memory management without libraries |
| Debugging Excellence |
When there's no OS to help, you become a debugging expert |
| Algorithm Implementation |
Schedulers, allocators, data structures without standard libraries |
| Appreciation for Abstractions |
Understanding why modern OS features exist and the problems they solve |
Key Insight: You don't need to build a production OS to benefit from this knowledge. Understanding how operating systems work makes you a better programmer at every level - from debugging tricky race conditions to optimizing performance-critical code.
Kernel vs Full Operating System
People often use "kernel" and "operating system" interchangeably, but they're different things. Understanding this distinction is crucial before you start building.
The Kernel: Heart of the OS
The kernel is the core component that runs in privileged mode with full hardware access. It provides the most fundamental services:
┌─────────────────────────────────────────────────────┐
│ User Applications │
│ (Chrome, VS Code, Games, Your Programs) │
├─────────────────────────────────────────────────────┤
│ System Services / Daemons │
│ (Window Manager, Network Stack, File Services) │
├─────────────────────────────────────────────────────┤
│ System Libraries │
│ (libc, Win32 API, Cocoa Framework) │
├─────────────────────────────────────────────────────┤
│ ═══════════════════════════════ │
│ SYSTEM CALL BOUNDARY │
│ ═══════════════════════════════ │
├─────────────────────────────────────────────────────┤
│ KERNEL │
│ ┌─────────────┬─────────────┬─────────────────┐ │
│ │ Process │ Memory │ File System │ │
│ │ Manager │ Manager │ Interface │ │
│ ├─────────────┼─────────────┼─────────────────┤ │
│ │ Device │ Inter-Proc │ Security │ │
│ │ Drivers │ Communic. │ Module │ │
│ └─────────────┴─────────────┴─────────────────┘ │
├─────────────────────────────────────────────────────┤
│ HARDWARE │
│ CPU RAM Disk Network │
└─────────────────────────────────────────────────────┘
The Full Operating System
A full operating system includes the kernel plus many additional components:
System Libraries
Standard C library (libc), math libraries, threading libraries. These wrap kernel system calls into convenient functions like printf() and malloc().
System Services
Background processes (daemons/services) like network managers, print spoolers, and logging services that run without user interaction.
User Interface
Command-line shells like bash, or graphical environments like GNOME, Windows Explorer, or macOS Finder.
What We're Building: In this series, we'll build a kernel first, then gradually add the components needed for a minimal but complete operating system: device drivers, filesystem, process management, a simple shell, and eventually graphics support.
Kernel Architectures
One of the first decisions in OS design is the kernel architecture. This fundamental choice affects everything from performance to reliability to how you'll structure your code.
Monolithic Kernels
In a monolithic kernel, all kernel services run in the same address space with full privileges. Think of it as a single large program that handles everything.
MONOLITHIC KERNEL
═══════════════════════════════════════════════════════
┌────────────────────────────────────────────────┐
│ USER SPACE (Ring 3) │
│ App1 App2 App3 │
└────────────────────────────────────────────────┘
│
════════════════════════
SYSTEM CALL
════════════════════════
│
┌────────────────────────────────────────────────┐
│ KERNEL SPACE (Ring 0) │
│ ┌──────────────────────────────────────────┐ │
│ │ Process Memory VFS Network │ │
│ │ Scheduler Manager TCP/IP Stack │ │
│ ├──────────────────────────────────────────┤ │
│ │ Device Drivers (disk, keyboard, GPU) │ │
│ ├──────────────────────────────────────────┤ │
│ │ Hardware Abstraction Layer (HAL) │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
│
HARDWARE
Advantages:
- Performance - No context switches between kernel components; direct function calls are fast
- Simplicity - Components can share data structures directly
- Mature ecosystem - Linux, FreeBSD, most classic UNIX systems use this model
Disadvantages:
- Stability risk - A bug in any driver can crash the entire system
- Security risk - A compromised driver has full system access
- Large codebase - Everything compiled together makes changes risky
Real-World Example: Linux Kernel
Linux is the most famous monolithic kernel. Despite being monolithic, it uses loadable kernel modules (LKMs) to add and remove drivers at runtime:
# See loaded kernel modules
lsmod
# Load a module (e.g., USB storage driver)
sudo modprobe usb_storage
# Remove a module
sudo rmmod usb_storage
This gives Linux some flexibility while maintaining the performance benefits of monolithic design.
Microkernels
A microkernel moves as much functionality as possible out of kernel space into user space. The kernel handles only the absolute essentials:
- Inter-process communication (IPC)
- Basic scheduling
- Low-level address space management
MICROKERNEL
═══════════════════════════════════════════════════════
┌────────────────────────────────────────────────┐
│ USER SPACE (Ring 3) │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ File │ │ Network │ │ Device │ ← SERVERS│
│ │ System │ │ Stack │ │ Drivers │ │
│ │ Server │ │ Server │ │ Servers │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └───────────┼───────────┘ │
│ │ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ App1 │ │ App2 │ │ App3 │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
└───────┼───────────┼───────────┼────────────────┘
│ │ │
════════════════════════════════════
IPC (Message Passing)
════════════════════════════════════
│ │ │
┌───────┴───────────┴───────────┴────────────────┐
│ KERNEL SPACE (Ring 0) │
│ ┌──────────────────────────────────────────┐ │
│ │ IPC │ Scheduler │ Basic MM │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
│
HARDWARE
Advantages:
- Reliability - Crash in a driver only affects that service, not the whole system
- Security - Smaller trusted computing base (TCB)
- Modularity - Services can be restarted independently
Disadvantages:
- Performance overhead - IPC is slower than direct function calls
- Complexity - Everything becomes a distributed systems problem
- Less mature tooling - Fewer developers, smaller ecosystems
Real-World Example: MINIX 3
MINIX was created by Andrew Tanenbaum for teaching. MINIX 3 is a true microkernel where even device drivers run in user space. Fun fact: MINIX code runs in every Intel CPU manufactured since 2008 as part of the Intel Management Engine!
Other microkernel examples: QNX (used in cars and medical devices), seL4 (formally verified secure kernel), GNU Hurd.
Hybrid Kernels
A hybrid kernel attempts to combine the best of both worlds. It runs more code in kernel space than a microkernel (for performance) but adopts microkernel ideas like message passing and modularity.
HYBRID KERNEL (Windows NT)
═══════════════════════════════════════════════════════
┌────────────────────────────────────────────────┐
│ USER SPACE │
│ Applications Subsystems (Win32, POSIX) │
└────────────────────────────────────────────────┘
│
═══════════════════════════
SYSTEM CALLS
═══════════════════════════
│
┌────────────────────────────────────────────────┐
│ KERNEL SPACE │
│ ┌──────────────────────────────────────────┐ │
│ │ Executive Services │ │
│ │ I/O Manager │ Memory │ Process │ │
│ │ PnP Manager │ Manager│ Manager │ │
│ ├──────────────────────────────────────────┤ │
│ │ Microkernel Core │ │
│ │ Thread Scheduling │ Exception Handling │ │
│ │ Interrupt Dispatch│ Synchronization │ │
│ ├──────────────────────────────────────────┤ │
│ │ Hardware Abstraction Layer │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
Examples: Windows NT/XP/10/11, macOS/XNU, BeOS/Haiku
For This Series: We'll build a monolithic kernel. It's the most straightforward architecture to learn and implement, and understanding it deeply will help you appreciate why alternatives exist.
Real-World Kernels Compared
Let's examine how major operating systems implement their kernels. Understanding their design decisions will inform our own choices.
Linux Kernel
At a Glance
- Architecture: Monolithic
- Created: 1991 by Linus Torvalds
- Language: C (with some assembly)
- License: GPL v2
- Lines of Code: ~30+ million
Linux started as a hobby project and grew into the most widely deployed kernel in history. It runs on everything from smartphones (Android) to supercomputers (500+ of the top 500).
Key Features:
- Loadable Kernel Modules - Add/remove drivers at runtime
- Virtual File System (VFS) - Unified interface for all filesystems
- Completely Fair Scheduler (CFS) - Sophisticated process scheduling
- Namespaces & cgroups - Foundation for containers (Docker)
/* Linux kernel entry point (simplified) - arch/x86/kernel/head_64.S → init/main.c */
asmlinkage __visible void __init start_kernel(void)
{
/* Lock scheduler to prevent races during boot */
local_irq_disable();
/* Initialize CPU, memory, and core subsystems */
setup_arch(&command_line); /* Architecture-specific setup */
setup_per_cpu_areas(); /* Per-CPU data structures */
mm_init(); /* Memory management */
sched_init(); /* Scheduler */
/* Initialize drivers and filesystems */
init_IRQ(); /* Interrupt handlers */
time_init(); /* Timekeeping */
console_init(); /* Console output */
/* Start the init process (PID 1) */
rest_init(); /* Creates kernel threads, runs /sbin/init */
}
Windows NT Kernel
At a Glance
- Architecture: Hybrid
- Created: 1993 by Dave Cutler's team
- Language: C, C++, assembly
- License: Proprietary
- Key Files: ntoskrnl.exe, hal.dll
Windows NT was designed from scratch by Dave Cutler (who previously designed VMS at DEC). Despite Microsoft often calling it a "hybrid" kernel, it runs most services in kernel mode for performance.
Key Features:
- Hardware Abstraction Layer (HAL) - Portable across architectures
- Object Manager - Everything is an object (files, processes, threads)
- Registry - Centralized configuration database
- Multiple Subsystems - Can run Win32, POSIX, OS/2 apps (historically)
/* Conceptual Windows kernel initialization (not actual code) */
void KiSystemStartup(LOADER_PARAMETER_BLOCK* LoaderBlock)
{
/* Phase 0: Basic initialization */
HalInitSystem(0, LoaderBlock); /* Initialize HAL */
KiInitializeKernel(); /* Kernel data structures */
KeInitializeInterrupts(); /* Set up IDT */
/* Phase 1: Start executive components */
ExInitSystem(); /* Executive layer */
ObInitSystem(); /* Object Manager */
SeInitSystem(); /* Security Reference Monitor */
MmInitSystem(); /* Memory Manager */
IoInitSystem(); /* I/O Manager - starts drivers */
/* Start Session Manager (smss.exe) - creates user sessions */
PsCreateSystemProcess("\\SystemRoot\\System32\\smss.exe");
}
macOS XNU Kernel
At a Glance
- Architecture: Hybrid
- Created: 2001 (roots in 1985)
- Language: C, C++
- License: APSL (open source)
- Based on: Mach + FreeBSD
XNU stands for "X is Not Unix" - it combines a Mach microkernel (from CMU) with FreeBSD's filesystem, networking, and POSIX APIs. It's a true hybrid that uses Mach for low-level operations and BSD for higher-level services.
Key Features:
- Mach Ports - IPC mechanism for communication between services
- IOKit - Object-oriented driver framework (C++)
- BSD Layer - POSIX-compliant APIs and networking
- Grand Central Dispatch - Kernel-level thread pooling
Kernel Comparison Summary
| Feature |
Linux |
Windows NT |
macOS XNU |
| Architecture |
Monolithic |
Hybrid |
Hybrid (Mach+BSD) |
| Drivers Run In |
Kernel space |
Kernel space |
Kernel space (IOKit) |
| IPC Mechanism |
Pipes, sockets, signals |
LPC/ALPC |
Mach ports |
| Open Source |
Yes (GPL) |
No |
Partially (APSL) |
| Learning Resources |
Excellent |
Limited |
Good |
The Complete Computing Stack
Before diving into kernel code, let's understand where the kernel fits in the complete picture - from silicon to applications.
Hardware Layer
At the bottom is the physical hardware:
Central Processing Unit (CPU)
The brain of the computer. Executes instructions, has registers for fast storage, and multiple privilege levels (rings). Modern CPUs have multiple cores, caches, and special features like virtual memory support.
Memory (RAM)
Fast, volatile storage where running programs live. The CPU can only directly execute code that's in RAM. Memory is organized as a linear array of bytes, each with an address.
Storage (Disk/SSD)
Persistent storage for files and programs. Much slower than RAM but survives power loss. Data must be copied to RAM before the CPU can execute it.
I/O Devices
Everything else: keyboard, mouse, display, network card, USB devices. Each has its own protocol for communication, which drivers abstract away.
Firmware (BIOS/UEFI)
When you press the power button, the CPU doesn't immediately run your operating system. First, it runs firmware - software built into the motherboard.
The Boot Process Overview
1. POWER ON
└─→ Power Supply sends "Power Good" signal to motherboard
2. CPU RESET
└─→ CPU starts executing at a fixed address (0xFFFFFFF0)
└─→ This address is mapped to firmware ROM
3. FIRMWARE INITIALIZATION (BIOS or UEFI)
└─→ POST (Power-On Self-Test)
└─→ Initialize hardware (RAM, USB, display)
└─→ Find bootable device (disk, USB, network)
└─→ Load boot sector / EFI application
4. BOOTLOADER (GRUB, Windows Boot Manager, etc.)
└─→ Present boot menu (optional)
└─→ Load kernel into memory
└─→ Pass control to kernel
5. KERNEL INITIALIZATION
└─→ Set up memory management
└─→ Initialize drivers
└─→ Start first user process
6. USER SPACE
└─→ Init system starts services
└─→ Login manager appears
└─→ You start doing work!
Legacy BIOS
The original PC firmware (1981). Limitations:
- 16-bit real mode only
- 1MB memory access
- MBR partition scheme (2TB max)
- No built-in security
Modern UEFI
Unified Extensible Firmware Interface (2005+). Benefits:
- 32-bit or 64-bit mode
- Full memory access
- GPT partitions (18EB max)
- Secure Boot, networking
Kernel & User Space
Modern CPUs have multiple privilege levels (called "rings" on x86). This is fundamental to OS security:
╔═══════════════════════════════════════════════════════╗
║ CPU PRIVILEGE RINGS (x86) ║
╠═══════════════════════════════════════════════════════╣
║ ║
║ ┌──────────────────────────────────────────────┐ ║
║ │ RING 3 (User Mode) │ ║
║ │ │ ║
║ │ Applications, Shells, Utilities │ ║
║ │ - Cannot access hardware directly │ ║
║ │ - Cannot execute privileged instructions │ ║
║ │ - Limited to its own address space │ ║
║ │ │ ║
║ │ ┌──────────────────────────────────────┐ │ ║
║ │ │ RING 0 (Kernel Mode) │ │ ║
║ │ │ │ │ ║
║ │ │ Operating System Kernel │ │ ║
║ │ │ - Full hardware access │ │ ║
║ │ │ - Execute any instruction │ │ ║
║ │ │ - Access all memory │ │ ║
║ │ │ │ │ ║
║ │ └──────────────────────────────────────┘ │ ║
║ │ │ ║
║ └──────────────────────────────────────────────┘ ║
║ ║
║ (Rings 1 & 2 exist but are rarely used in modern OS) ║
╚═══════════════════════════════════════════════════════╝
Why this separation matters:
- Protection - A buggy application can't crash the whole system
- Security - Malware can't directly modify kernel memory
- Stability - The kernel can terminate misbehaving programs
System Calls: The Bridge
User programs need kernel services (file access, network, memory). They can't just call kernel functions directly (different privilege level). Instead, they use system calls:
/* User space: "I want to write to a file" */
write(fd, buffer, size); /* This triggers a system call */
/* Internally:
1. Arguments placed in registers
2. "syscall" instruction executed
3. CPU switches to Ring 0
4. Kernel writes data to file
5. CPU switches back to Ring 3
6. Control returns to user program
*/
We'll implement system calls in Phase 8.
Series Overview & Learning Path
This series takes you from zero to a working operating system. Here's the journey:
Prerequisites
- C Programming - Comfortable with pointers, structs, memory allocation
- Basic Computer Architecture - Registers, memory, stack concept
- Command Line - Basic terminal/shell usage
- Willingness to Learn Assembly - We'll teach what you need
Development Milestones
Phases 1-4: Hello, Hardware!
- Boot process fundamentals
- Your first bootloader (assembly)
- Transition to 32-bit mode
- Screen output and keyboard input
Milestone: Kernel prints text and accepts keyboard input
Phases 5-7: Core Systems
- Interrupt handling
- Memory management (paging, allocation)
- Disk access and filesystems
Milestone: Kernel manages memory, reads/writes files
Phases 8-10: User Space
- Processes and multitasking
- System calls
- Loading and running programs
- Shell implementation
Milestone: Run multiple programs, interactive shell
Phases 11-17: Advanced
- 64-bit mode and UEFI
- Graphics and windowing
- Device drivers
- Performance and security
Milestone: Modern, full-featured operating system
Tools You'll Use
| Tool |
Purpose |
Why We Use It |
| QEMU |
Emulator |
Test your OS without rebooting real hardware |
| GCC Cross-Compiler |
C Compiler |
Compile code for your custom target (not your host OS) |
| NASM |
Assembler |
Low-level bootstrap code and hardware interaction |
| GNU LD |
Linker |
Combine object files into the kernel binary |
| GDB |
Debugger |
Step through kernel code, inspect memory |
| Make |
Build System |
Automate compilation and linking |
Development Environment: We'll set up everything in
Phase 1. Works on Windows (WSL), macOS, and Linux.
Exercises
Before moving to Phase 1, strengthen your foundation with these exercises:
Exercise 1: Explore Your System
Linux/macOS users:
# View kernel version
uname -a
# See kernel boot messages
dmesg | head -50
# List loaded kernel modules
lsmod
# View system calls made by a program
strace ls
Windows users:
# View system information (PowerShell)
systeminfo
# View kernel drivers
driverquery
# View system calls (requires Process Monitor from Sysinternals)
Question: What kernel version is your computer running? How many modules are loaded?
Exercise 2: Memory Concepts
Write a C program that prints the addresses of:
#include <stdio.h>
#include <stdlib.h>
int global_variable = 42;
void sample_function(void) {
int local_variable = 100;
printf("Local variable address: %p\n", (void*)&local_variable);
}
int main() {
int stack_variable = 10;
int *heap_variable = malloc(sizeof(int));
printf("Global variable address: %p\n", (void*)&global_variable);
printf("Stack variable address: %p\n", (void*)&stack_variable);
printf("Heap variable address: %p\n", (void*)heap_variable);
printf("Function address: %p\n", (void*)&sample_function);
printf("Main address: %p\n", (void*)&main);
sample_function();
free(heap_variable);
return 0;
}
Questions: Are stack addresses higher or lower than heap addresses on your system? What does this tell you about memory layout?
Exercise 3: Research Questions
- What is the difference between a process and a thread?
- Why can't user programs directly access hardware (like writing to the screen)?
- What happens if you try to execute a "privileged instruction" from user space?
- Research: What is a context switch? Why is it expensive?
Next Steps
You now understand:
- What an operating system is and why we need one
- The difference between kernel and full OS
- Major kernel architectures (monolithic, microkernel, hybrid)
- How Linux, Windows, and macOS implement their kernels
- The complete computing stack from hardware to applications
- The learning path ahead of us
Coming Up in Phase 1: We'll dive into the boot process - what actually happens when you press the power button. You'll set up your development environment with a cross-compiler and emulator, and understand exactly how the CPU transitions from firmware to operating system code.
Continue the Series
Phase 1: How a Computer Starts
Learn about CPU reset state, BIOS vs UEFI, boot sequences, and set up your cross-compiler and emulator environment.
Read Article
Phase 2: Real Mode - First Steps Near Hardware
Write your first bootloader, understand real mode memory, and interact directly with hardware via BIOS interrupts.
Read Article
Phase 3: Entering Protected Mode
Transition to 32-bit protected mode, set up the GDT, and start running C code in your kernel.
Read Article