TRACK A OS KERNEL PROJECTS
Operating Systems & Kernel Development — Learning Projects
Track A: Hard Mode — For kernel dev, OS teams, hypervisor/virtualization, cloud infra internals
This is the “hard mode” track for good reason. These projects will take you from observing the kernel from userspace to actually writing code that runs in kernel space.
Core Concept Analysis
The topics in this track form an interconnected system. Here’s how they relate:
| Concept | What You Need to Understand |
|---|---|
| Syscall paths | How control transfers from user code → kernel → back, the syscall table, context switching overhead |
| Process lifecycle | fork/exec/wait, process states (running, sleeping, zombie), exit, process hierarchy |
| Virtual memory | Page tables, address spaces, memory mapping, copy-on-write, demand paging |
| Page faults | Major vs minor faults, fault handlers, memory-mapped files, swapping |
| Scheduling | Run queues, time slices, priorities, preemption, scheduler classes (CFS, RT) |
| Interrupts | Hardware interrupts, interrupt handlers, top/bottom halves, softirqs |
| Device drivers | Character vs block devices, file_operations, ioctl, kernel APIs |
| Kernel/user boundary | Protection rings, privilege levels, copying data across boundary |
| OS-level locks | Spinlocks, mutexes, semaphores, RCU, lock ordering, deadlock prevention |
Project 1: Syscall Tracer (strace clone)
- File: TRACK_A_OS_KERNEL_PROJECTS.md
- Programming Language: C
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 3. The “Service & Support” Model
- Difficulty: Level 3: Advanced
- Knowledge Area: OS Internals / Debugging
- Software or Tool: ptrace
- Main Book: “The Linux Programming Interface” by Michael Kerrisk
What you’ll build: A tool that intercepts and logs every system call a program makes, showing the syscall name, arguments, and return values in real-time.
Why it teaches OS internals: Building strace forces you to understand the exact boundary between user and kernel space. You’ll use ptrace() to stop a process at every syscall, decode the syscall number from registers, and understand how arguments are passed. This is the single best way to see the kernel/user boundary in action.
Core challenges you’ll face:
- Decoding syscall numbers to names (maps to syscall table structure)
- Reading arguments from registers and memory (maps to calling conventions, kernel/user boundary)
- Handling multi-threaded programs (maps to process lifecycle, threading model)
- Following child processes through fork/exec (maps to process lifecycle)
- Dealing with restartable syscalls after signals (maps to interrupt handling)
Resources for key challenges:
- “The Linux Programming Interface” by Michael Kerrisk (Ch. 26: Process Tracing) - The definitive guide to ptrace
- “Computer Systems: A Programmer’s Perspective” by Bryant & O’Hallaron (Ch. 8) - Exception control flow and syscalls
Key Concepts:
- ptrace mechanism: “The Linux Programming Interface” Ch. 26 - Michael Kerrisk
- x86-64 calling conventions: “Computer Systems: A Programmer’s Perspective” Ch. 3 - Bryant & O’Hallaron
- Syscall tables: Linux kernel source
arch/x86/entry/syscalls/syscall_64.tbl - Process states: “Operating Systems: Three Easy Pieces” Ch. 4 - Arpaci-Dusseau
Difficulty: Intermediate Time estimate: 2-3 weeks Prerequisites: C programming, basic understanding of processes, comfort reading man pages
Real world outcome:
- Run
./mystrace ls -laand see every syscall:open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3 - Output should be readable like real strace, showing timing, arguments, return codes
- Can trace any program on your system and understand what it’s actually doing
Learning milestones:
- Successfully intercept and print syscall numbers → You understand the ptrace state machine
- Decode arguments including strings and structs → You understand memory layout and kernel/user data transfer
- Handle fork/exec and follow children → You understand process lifecycle deeply
- Support multi-threaded programs → You understand the relationship between processes and threads at OS level
Project 2: Memory Allocator (malloc/free from scratch)
- File: TRACK_A_OS_KERNEL_PROJECTS.md
- Programming Language: C
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Memory Management / Systems Programming
- Software or Tool: sbrk / mmap
- Main Book: “Computer Systems: A Programmer’s Perspective” by Bryant & O’Hallaron
What you’ll build: A complete memory allocator that replaces malloc/free, using only brk() and mmap() syscalls, with visual debugging output showing heap state.
Why it teaches OS internals: malloc is the interface between your program and the kernel’s virtual memory system. By implementing it, you’ll understand why the heap exists, how the kernel grows your address space, the difference between virtual and physical memory, and why memory fragmentation happens.
Core challenges you’ll face:
- Managing the program break with
brk()/sbrk()(maps to virtual memory, syscalls) - Using
mmap()for large allocations (maps to virtual memory, page faults) - Implementing free lists and coalescing (maps to memory management algorithms)
- Handling alignment requirements (maps to hardware memory model)
- Debugging memory corruption (maps to understanding address space layout)
Resources for key challenges:
- “Computer Systems: A Programmer’s Perspective” Ch. 9.9 - Detailed malloc implementation walkthrough
- “Operating Systems: Three Easy Pieces” Ch. 17 - Free space management
Key Concepts:
- Virtual address space layout: “Computer Systems: A Programmer’s Perspective” Ch. 9 - Bryant & O’Hallaron
- Free list management: “Operating Systems: Three Easy Pieces” Ch. 17 - Arpaci-Dusseau
- mmap syscall: “The Linux Programming Interface” Ch. 49 - Michael Kerrisk
- Memory alignment: “C Interfaces and Implementations” Ch. 5 - David Hanson
Difficulty: Intermediate Time estimate: 2-3 weeks Prerequisites: C, pointers, basic understanding of processes
Real world outcome:
LD_PRELOAD=./mymalloc.so ./some_program- Replace system malloc with yours- Visual heap dump:
[BLOCK 0x1000: 64 bytes USED] [BLOCK 0x1040: 128 bytes FREE] ... - Run benchmarks comparing your allocator to glibc malloc
- Successfully run complex programs (even a shell) using your allocator
Learning milestones:
- Basic allocation with brk works → You understand heap growth and the program break
- Free works with coalescing → You understand fragmentation and metadata management
- mmap for large allocations → You understand different memory mapping strategies
- Can run real programs → You’ve built something production-quality
Project 3: Process Scheduler Visualization Tool
- File: TRACK_A_OS_KERNEL_PROJECTS.md
- Programming Language: C
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 3. The “Service & Support” Model
- Difficulty: Level 3: Advanced
- Knowledge Area: OS Scheduler / Kernel Internals
- Software or Tool: Linux Scheduler (CFS)
- Main Book: “Linux Kernel Development” by Robert Love
What you’ll build: A tool that visualizes the Linux scheduler in real-time, showing which processes are running on which CPUs, context switches, runqueue depth, and scheduling decisions.
Why it teaches OS internals: The scheduler is the heart of the OS. By building a tool to observe it, you’ll learn how the kernel decides what runs, why processes get preempted, and how modern schedulers balance fairness with performance.
Core challenges you’ll face:
- Reading scheduler data from
/procand tracefs (maps to kernel/user data interfaces) - Understanding CFS vruntime and load balancing (maps to scheduling algorithms)
- Tracking context switches in real-time (maps to process lifecycle, interrupts)
- Correlating CPU time with priority (maps to scheduler internals)
- Visualizing multi-core scheduling (maps to SMP considerations)
Resources for key challenges:
- “Operating Systems: Three Easy Pieces” Ch. 7-10 - Scheduling chapters
- “Linux Kernel Development” by Robert Love Ch. 4 - CFS scheduler deep dive
Key Concepts:
- Completely Fair Scheduler (CFS): “Linux Kernel Development” Ch. 4 - Robert Love
- Process states and transitions: “Operating Systems: Three Easy Pieces” Ch. 4 - Arpaci-Dusseau
- /proc filesystem: “The Linux Programming Interface” Ch. 12 - Michael Kerrisk
- CPU affinity: “The Linux Programming Interface” Ch. 35 - Michael Kerrisk
Difficulty: Intermediate Time estimate: 2 weeks Prerequisites: C, understanding of basic scheduling concepts
Real world outcome:
- Terminal UI showing real-time CPU utilization per core with process names
- Timeline view showing context switches:
[CPU0: nginx(1234) → postgres(5678) → nginx(1234)] - Statistics: context switches/sec, average time slice, runqueue depth
- Can identify scheduling problems: “Process X is getting starved because…”
Learning milestones:
- Read and parse /proc/schedstat → You understand kernel-exported scheduler data
- Visualize context switches → You understand preemption and time slicing
- Track vruntime progression → You understand CFS fairness model
- Correlate with CPU affinity → You understand multi-core scheduling
Project 4: Page Fault Analyzer
- File: TRACK_A_OS_KERNEL_PROJECTS.md
- Programming Language: C
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 3. The “Service & Support” Model
- Difficulty: Level 4: Expert
- Knowledge Area: Virtual Memory / Kernel Tracing
- Software or Tool: perf_event_open
- Main Book: “Operating Systems: Three Easy Pieces” by Arpaci-Dusseau
What you’ll build: A tool that monitors page faults in running programs, distinguishing major from minor faults, showing which virtual addresses faulted, and mapping faults to source code locations.
Why it teaches OS internals: Page faults are where virtual memory becomes real. By observing them, you’ll understand demand paging, copy-on-write, memory-mapped files, and why adding RAM sometimes doesn’t help performance.
Core challenges you’ll face:
- Using
perf_event_open()to capture page faults (maps to kernel tracing interfaces) - Distinguishing major vs minor faults (maps to page fault types, I/O)
- Correlating fault addresses with memory regions from
/proc/pid/maps(maps to virtual memory layout) - Understanding COW and lazy allocation (maps to memory optimization strategies)
- Symbolizing addresses to function names (maps to debugging/profiling)
Resources for key challenges:
- “Operating Systems: Three Easy Pieces” Ch. 21-23 - Virtual memory and paging
- “Computer Systems: A Programmer’s Perspective” Ch. 9 - Virtual memory
Key Concepts:
- Page fault handling: “Operating Systems: Three Easy Pieces” Ch. 21 - Arpaci-Dusseau
- Memory mapping: “The Linux Programming Interface” Ch. 49 - Michael Kerrisk
- perf_event_open: man page + kernel documentation
- /proc/pid/maps format: “The Linux Programming Interface” Ch. 48 - Michael Kerrisk
Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: C, understanding of virtual memory basics
Real world outcome:
./pagefault-analyzer ./my_program- Output shows:
MINOR fault at 0x7fff5a2b3000 (stack growth), MAJOR fault at 0x400000 (loading code from disk) - Heat map of which memory regions cause the most faults
- Can explain: “Your program has 10,000 major faults because it’s not pre-faulting the mmap’d file”
Learning milestones:
- Capture page faults with counts → You understand the basic fault mechanism
- Distinguish major/minor → You understand the role of disk I/O in paging
- Map to source regions → You understand address space layout in detail
- Give optimization advice → You can apply this knowledge to real performance problems
Project 5: Linux Kernel Module — Character Device Driver
- File: TRACK_A_OS_KERNEL_PROJECTS.md
- Programming Language: C
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 3. The “Service & Support” Model
- Difficulty: Level 4: Expert
- Knowledge Area: Kernel Development / Drivers
- Software or Tool: Linux Kernel Headers
- Main Book: “Linux Device Drivers” by Corbet, Rubini, Kroah-Hartman
What you’ll build: A character device driver (/dev/mydevice) that implements a simple ring buffer in kernel space, accessible from userspace via read/write/ioctl.
Why it teaches OS internals: This is where you cross the boundary. You’ll write code that runs in kernel space, manage kernel memory, handle concurrent access, and understand why the kernel is designed the way it is.
Core challenges you’ll face:
- Setting up kernel module build environment (maps to kernel build system)
- Implementing
file_operations(open, read, write, release, ioctl) (maps to VFS layer) - Managing kernel memory with kmalloc/kfree (maps to kernel memory management)
- Handling concurrent access with spinlocks/mutexes (maps to OS-level locks)
- Copying data between user and kernel space (maps to kernel/user boundary)
- Debugging without crashing your system (maps to kernel debugging)
Resources for key challenges:
- “Linux Device Drivers” by Corbet, Rubini, Kroah-Hartman (Ch. 3) - Character drivers
- “Linux Kernel Development” by Robert Love - General kernel programming
Key Concepts:
- Kernel modules: “Linux Device Drivers” Ch. 2 - Corbet et al.
- Character devices: “Linux Device Drivers” Ch. 3 - Corbet et al.
- Kernel memory allocation: “Linux Kernel Development” Ch. 12 - Robert Love
- Kernel synchronization: “Linux Kernel Development” Ch. 10 - Robert Love
- copy_to_user/copy_from_user: “Linux Device Drivers” Ch. 3 - Corbet et al.
Difficulty: Advanced Time estimate: 3-4 weeks Prerequisites: Strong C, completed at least one userspace project above, comfortable with system crashes
Real world outcome:
insmod mydriver.koloads your moduleecho "hello" > /dev/mydevicewrites to kernel ring buffercat /dev/mydevicereads back (FIFO)./myctl --stats(via ioctl) shows buffer stats- Check
dmesgfor your kernel printk messages
Learning milestones:
- Module loads/unloads cleanly → You understand kernel module lifecycle
- Basic read/write works → You understand file_operations and the VFS
- Handle concurrent access → You understand kernel locking primitives
- ioctl implementation → You understand custom kernel-user interfaces
- Survives stress testing → You’ve written robust kernel code
Project 6: Userspace Thread Library (Green Threads)
- File: TRACK_A_OS_KERNEL_PROJECTS.md
- Programming Language: C / Assembly
- Coolness Level: Level 5: Pure Magic (Super Cool)
- Business Potential: 4. The “Open Core” Infrastructure
- Difficulty: Level 5: Master
- Knowledge Area: OS Architecture / Concurrency
- Software or Tool: Context Switching
- Main Book: “Operating Systems: Three Easy Pieces” by Arpaci-Dusseau
What you’ll build: A cooperative threading library that implements thread creation, yielding, and a round-robin scheduler, entirely in userspace without kernel thread support.
Why it teaches OS internals: By building your own scheduler and context switching, you’ll understand exactly what the kernel does thousands of times per second. The constraints of userspace threading also illuminate why kernel threads and preemption exist.
Core challenges you’ll face:
- Saving and restoring CPU state (registers, stack pointer) (maps to context switching)
- Allocating and managing per-thread stacks (maps to memory management)
- Implementing a scheduler and run queue (maps to scheduling)
- Making it work with blocking I/O (maps to understanding blocking vs non-blocking)
- Signal handling with custom stacks (maps to interrupts, signals)
Resources for key challenges:
- “Operating Systems: Three Easy Pieces” Ch. 26-28 - Concurrency introduction
- “Computer Systems: A Programmer’s Perspective” Ch. 8 - Control flow
Key Concepts:
- Context switching: “Operating Systems: Three Easy Pieces” Ch. 6 - Arpaci-Dusseau
- setjmp/longjmp: “C Programming: A Modern Approach” Ch. 24 - K.N. King
- Stack management: “Computer Systems: A Programmer’s Perspective” Ch. 3 - Bryant & O’Hallaron
- Scheduling algorithms: “Operating Systems: Three Easy Pieces” Ch. 7-9 - Arpaci-Dusseau
Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Strong C, assembly basics, understanding of calling conventions
Real world outcome:
thread_create(worker_function, arg);
thread_create(another_worker, arg2);
scheduler_run(); // Runs both, switching on yield()
- Demo program with multiple threads printing interleaved output
- Can implement a simple cooperative web server using your threads
- Benchmark: show context switch overhead (nanoseconds)
Learning milestones:
- Basic context switch works → You understand what state defines a “thread”
- Multiple threads round-robin → You understand scheduling decisions
- Thread exit and cleanup → You understand resource management
- Works with real workloads → You’ve built something useful
Project 7: Interrupt Latency Profiler
- File: TRACK_A_OS_KERNEL_PROJECTS.md
- Programming Language: C
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 3. The “Service & Support” Model
- Difficulty: Level 4: Expert
- Knowledge Area: OS Performance / Kernel
- Software or Tool: ftrace / eBPF
- Main Book: “Systems Performance” by Brendan Gregg
What you’ll build: A tool that measures and visualizes interrupt latency on your system, showing how long it takes from hardware interrupt to handler execution, and identifying sources of latency.
Why it teaches OS internals: Interrupts are how hardware talks to software. By measuring them, you’ll understand interrupt handlers, top/bottom halves, interrupt masking, and why real-time systems are hard.
Core challenges you’ll face:
- Accessing interrupt statistics from /proc/interrupts (maps to interrupt subsystem)
- Using ftrace to trace interrupt handlers (maps to kernel tracing)
- Understanding IRQ affinity and distribution (maps to SMP interrupt handling)
- Measuring time accurately at microsecond scale (maps to timekeeping)
- Correlating latency spikes with system activity (maps to system analysis)
Key Concepts:
- Interrupt handling: “Linux Kernel Development” Ch. 7 - Robert Love
- Top/bottom halves: “Linux Kernel Development” Ch. 8 - Robert Love
- ftrace: Kernel documentation + Steven Rostedt’s articles
- /proc/interrupts: “Understanding the Linux Kernel” Ch. 4 - Bovet & Cesati
Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Understanding of userspace profiling, basic kernel concepts
Real world outcome:
- Real-time display:
IRQ 16 (eth0): avg 2.3μs, max 150μs, count 45032/sec - Histogram of latencies per interrupt source
- Alert when latency exceeds threshold
- Can diagnose: “Your network latency spikes happen when IRQ 16 and IRQ 18 hit the same CPU”
Learning milestones:
- Parse /proc/interrupts → You understand interrupt accounting
- Trace with ftrace → You understand kernel tracing infrastructure
- Measure latencies accurately → You understand timekeeping challenges
- Correlate with system events → You can debug real interrupt issues
Project Comparison Table
| Project | Difficulty | Time | Depth of Understanding | Fun Factor | Topics Covered |
|---|---|---|---|---|---|
| Syscall Tracer | Intermediate | 2-3 weeks | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Syscalls, process lifecycle, kernel/user boundary |
| Memory Allocator | Intermediate | 2-3 weeks | ⭐⭐⭐⭐ | ⭐⭐⭐ | Virtual memory, page faults, syscalls |
| Scheduler Visualizer | Intermediate | 2 weeks | ⭐⭐⭐ | ⭐⭐⭐⭐ | Scheduling, process lifecycle |
| Page Fault Analyzer | Advanced | 2-3 weeks | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | Virtual memory, page faults |
| Kernel Module | Advanced | 3-4 weeks | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Device drivers, locks, kernel/user boundary |
| Thread Library | Advanced | 2-3 weeks | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | Scheduling, locks, process lifecycle |
| Interrupt Profiler | Advanced | 2 weeks | ⭐⭐⭐⭐ | ⭐⭐⭐ | Interrupts, scheduling |
Recommended Learning Path
Given this is “hard mode,” here’s the progression I recommend:
Phase 1: Observe the Kernel from Outside (Weeks 1-5)
- Syscall Tracer - Start here. It’s the best way to see the kernel/user boundary without writing kernel code.
- Memory Allocator - Builds on syscall knowledge, teaches virtual memory deeply.
Phase 2: Understand Scheduling and Concurrency (Weeks 6-9)
- Thread Library - Forces you to implement what the scheduler does.
- Scheduler Visualizer - Now observe the real kernel scheduler with informed eyes.
Phase 3: Cross into Kernel Space (Weeks 10-15)
- Kernel Module - The real thing. Everything before this was preparation.
- Page Fault Analyzer - Combines userspace tooling with deep kernel knowledge.
- Interrupt Profiler - Capstone project tying it all together.
Final Comprehensive Project: Mini Operating System Kernel
What you’ll build: A minimal operating system that boots on real hardware (or QEMU), implements protected mode, basic virtual memory with paging, a simple process model with context switching, a basic syscall interface, and a simple shell.
Why this is the ultimate project: This synthesizes everything. You can’t fake understanding when you’re writing the code that sets up page tables, handles interrupts, and switches between processes.
Core challenges you’ll face:
- Bootloader and protected mode setup (maps to hardware initialization)
- Setting up GDT, IDT, TSS (maps to x86 architecture)
- Implementing paging and virtual memory (maps to virtual memory internals)
- Writing interrupt handlers (maps to interrupts)
- Implementing basic syscalls (maps to syscall paths, kernel/user boundary)
- Context switching between processes (maps to scheduling, process lifecycle)
- Basic device drivers (keyboard, screen) (maps to device drivers)
- Kernel synchronization primitives (maps to OS-level locks)
Resources for key challenges:
- “Operating Systems: Three Easy Pieces” - Conceptual foundation
- OSDev Wiki (wiki.osdev.org) - Practical x86 OS development
- “Computer Systems: A Programmer’s Perspective” Ch. 9 - Virtual memory implementation
- James Molloy’s kernel tutorials - Step-by-step x86 kernel
Key Concepts:
- x86 protected mode: OSDev Wiki + Intel manuals
- Paging setup: “Operating Systems: Three Easy Pieces” Ch. 18-20 - Arpaci-Dusseau
- Interrupt Descriptor Table: “Computer Systems: A Programmer’s Perspective” Ch. 8 - Bryant & O’Hallaron
- Context switching: “Operating Systems: Three Easy Pieces” Ch. 6 - Arpaci-Dusseau
- System call implementation: “The Linux Programming Interface” Ch. 3 - Michael Kerrisk (for design)
Difficulty: Expert Time estimate: 2-3 months Prerequisites: All projects above, x86 assembly, strong C, patience
Real world outcome:
- Boot your OS in QEMU:
qemu-system-i386 -kernel myos.bin - See your kernel print “MyOS v0.1”
- Type commands in your shell
- Run multiple processes that time-slice
psshows running processes with PIDsmemshows memory map with page table info- Handle a page fault gracefully (not crash)
Learning milestones:
- Boot to protected mode → You understand x86 boot process
- Paging works, can map/unmap pages → You understand virtual memory at the hardware level
- Keyboard interrupt works → You understand interrupt handling
- Two processes context switch → You understand scheduling at the deepest level
- Syscalls work → You understand the complete kernel/user boundary
- Shell runs user programs → You’ve built an operating system
Final Notes
Why this order matters: Each project builds mental models that the next project requires. The syscall tracer shows you the boundary; the allocator makes you use it; the thread library makes you implement scheduling; the kernel module puts you on the other side; and the mini-OS makes you build the whole thing.
The reality check from your curriculum is accurate: This path has the highest prestige and highest difficulty. The jobs are fewer but they’re the jobs that really matter—kernel teams at Linux distros, hypervisor teams at VMware/AWS/Google, OS teams at Apple/Microsoft, embedded systems, and security research.
Strong OSS signaling: Every one of these projects can go on GitHub. A working strace clone or kernel module demonstrates skills that can’t be faked in an interview.
Start with the syscall tracer. When you can explain every line of output from strace ls, you’re ready for the rest.