Chapter 19 — Per-Process Address Spaces and CR3 Switching

Chapter 19 — Per-Process Address Spaces and CR3 Switching
This entry is part 19 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 18, user programs gained a much more realistic syscall interface: But all user processes still shared the same page directory. That means every process saw the same user mappings: This chapter gives each process its own address space. The new model becomes: When the scheduler switches between processes, it will also switch CR3.

Chapter 18 — File-Descriptor Syscalls and a Tiny User-Mode Console Program

Chapter 18 — File-Descriptor Syscalls and a Tiny User-Mode Console Program
This entry is part 18 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 17, we added the first minimal process object: That was a big step, but the syscall interface was still a little too artificial. This chapter makes user programs feel more like real programs by adding a tiny file-descriptor-style interface: We will update SYS_WRITE to use a file descriptor, add SYS_READ, and run a

Chapter 17 — Minimal Processes, User Memory Copying, and More Robust Syscalls

Chapter 17 — Minimal Processes, User Memory Copying, and More Robust Syscalls
This entry is part 17 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 16, we proved the biggest privilege milestone so far: But the user-mode test was still mostly a raw thread experiment. The kernel did not yet have a real object representing a user program. This chapter adds the first process abstraction. A process will own: We will also add safer user-memory access helpers: and

Chapter 16 — Entering User Mode and Returning Through Syscalls

Chapter 16 — Entering User Mode and Returning Through Syscalls
This entry is part 16 of 19 in the series Writing A Linux Style Operating System From Scratch

We now have an interactive, preemptive kernel with memory management, blocking, synchronization, keyboard input, terminal editing, and a monitor. So far, however, everything runs in ring 0. That means every thread has full kernel privilege. There is no separation between kernel code and user code yet. This chapter adds the first user-mode milestone: Intel’s IA-32

Chapter 15 — Command Tables, Argument Parsing, and Shift-Aware Keyboard Input

Chapter 15 — Command Tables, Argument Parsing, and Shift-Aware Keyboard Input
This entry is part 15 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 14, we added the first interactive kernel monitor: That worked, but the monitor command parser was still a chain of if statements: That is fine for five commands, but it does not scale. This chapter cleans that up by adding: The keyboard improvement matters because our monitor is interactive now. A monitor where

Chapter 14 — Terminal Line Discipline and a Kernel Monitor

Chapter 14 — Terminal Line Discipline and a Kernel Monitor
This entry is part 14 of 19 in the series Writing A Linux Style Operating System From Scratch

At this point our kernel has enough machinery to become interactive: Now we will build two new layers: The terminal line discipline turns raw keyboard characters into editable input lines. It handles: The kernel monitor is a small command loop: This is not user space yet. It is still a kernel thread. But it gives

Chapter 13 — Mutexes, Semaphores, and a Console Lock

Chapter 13 — Mutexes, Semaphores, and a Console Lock
This entry is part 13 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 12, we added wait queues and blocking keyboard input: Now we need synchronization primitives that ordinary kernel code can use. This chapter adds: A mutex provides mutual exclusion: only one thread may hold the protected resource at a time. OSDev describes a mutex as a mutual-exclusion mechanism, similar to a binary semaphore, used

Chapter 12 – Wait Queues and Blocking Keyboard Input

Chapter 12 – Wait Queues and Blocking Keyboard Input
This entry is part 12 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 11, we added the first blocking primitive: That gave the scheduler a way to remove a thread from the ready queue until a future timer tick. Now we need a more general primitive: This is the foundation for real kernel I/O. A keyboard reader should not spin like this: It should block: This

Chapter 11 — Blocking Primitives, Sleep Queues, and Scheduler Hygiene

Chapter 11 — Blocking Primitives, Sleep Queues, and Scheduler Hygiene
This entry is part 11 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 10, we added timer-driven preemption: Now we need the next scheduler capability: blocking. A runnable thread competes for CPU time. A blocked or sleeping thread does not. OSDev describes a blocking process as one that waits for an event, such as a semaphore or message, and is removed from the active scheduling queue

Chapter 10 — Timer-Driven Preemptive Multitasking

This entry is part 10 of 19 in the series Writing A Linux Style Operating System From Scratch

In Chapter 9, we built cooperative multitasking: That works, but it has a major weakness: A thread like that can monopolize the CPU forever. This chapter adds the next step: timer-driven preemption. With preemptive scheduling: OSDev describes preemptive multitasking as scheduling where an interrupt, usually timer-driven, allows the kernel to take control away from the