The Operating System and Processes: Kernel, User Space, and the PCB
Hook #
Every program you've ever run was lied to about being alone. In the last course you saw the first half of the lie — virtual memory convinces each program it owns all of memory. This course reveals the liar: the operating system, and specifically its innermost part, the kernel. The kernel is the program that runs all the other programs — it decides who gets the CPU and for how long, hands out memory, mediates every disk and network access, and keeps a hundred processes believing each has the machine to itself. The abstraction it sells is the process: a running program with its own memory, its own view of the CPU, its own little universe. This lesson is about what a process actually is underneath that abstraction, and how the kernel keeps dozens of them running on a CPU that can, physically, only do one thing at a time.
What you'll be able to do by the end of this lesson #
- Explain the kernel/user-space split and why it exists (the kernel runs privileged; user programs are sandboxed and must ask the kernel — via system calls — for anything dangerous).
- Define a process precisely: a program in execution, with its address space, registers, and OS bookkeeping (the Process Control Block).
- Explain what a context switch is, and connect it back to the interrupt mechanism from the last course (save state, switch, restore state).
- Explain how one CPU runs many processes through time-sharing, and why it feels simultaneous even though it's rapid switching.
A quick try before we start #
Open a process viewer (Activity Monitor, htop, Task Manager) right now. You'll see dozens — maybe hundreds — of processes, and a CPU with a handful of cores. Before reading: how can 300 processes "run at once" on 8 cores? Sit with the arithmetic. The answer — the kernel switches between them fast enough that each appears continuous — is the central trick of this lesson, and it's the same trick a single-threaded event loop uses to feel concurrent.
Why this matters here #
You have spent your career on top of an operating system, and mostly been able to ignore it — until you couldn't. When a deploy is "killed by the OOM killer," when a process won't die and you reach for kill -9, when you tune the number of Puma workers or Sidekiq processes, when a zombie process lingers, when you wonder what fork actually does to your Rails app's memory — those are all moments where the OS abstraction cracks and you need to know what's underneath. This course is where "the OS" stops being a black box and becomes a set of mechanisms you understand. A senior engineer who understands processes debugs production incidents that a junior one can only stare at.
This lesson is also the direct sequel to the last course. The interrupt mechanism you learned for I/O — save state, jump to a handler, restore state — is exactly how the kernel takes control away from a running process to run another. A timer interrupt fires, the CPU traps into the kernel, the kernel saves the current process's registers into its PCB, loads another process's registers, and returns — and now a different program is running. Virtual memory (last course) is what makes that safe: each process's address space is isolated by its own page table, so the one the kernel switches to can't see the one it switched from. Processes are virtual memory plus interrupts plus scheduling, assembled into an abstraction.
The engineer's lens #
The idea to internalize is the process as the OS's unit of isolation and accounting — and it's the same "give each tenant a sandboxed, bookkept container" pattern you use at every layer above. A process bundles together everything a running program needs (its memory, open files, registers, a unique PID) and everything the OS needs to manage it (its state, priority, parent, resource usage) into one record: the Process Control Block. When you deploy each service in its own container, when you give each tenant an isolated schema, when you run each job in its own worker — you're recreating the process's core idea at a higher altitude: a bounded unit that's isolated from its neighbors and independently schedulable and killable. The OS invented multi-tenancy, and the process is its atom.
The second lens is the kernel/user-space boundary, which is one of the most important security and reliability ideas in computing. User code runs unprivileged — it literally cannot execute the instructions that touch hardware, remap memory, or talk to devices. When your program needs one of those, it makes a system call: a controlled, checked doorway into the kernel. This is the original "principle of least privilege" and the original "validated API boundary" — user code can't be trusted with the hardware, so it must go through a narrow, guarded interface. Every time you put an untrusted client behind a validating API, or run tenant code in a sandbox that can only call approved functions, you're rebuilding the syscall boundary. And the cost of crossing it (a syscall is expensive — a mode switch into the kernel and back) is why high-performance systems batch syscalls, use io_uring, or avoid them in hot loops. That cost is a real number you'll optimize against later.
What to focus on in OSTEP (Process chapters) #
- "The Abstraction: The Process" first. Nail down process states (running, ready, blocked) and the PCB. The state machine — a process moves between running, ready-to-run, and blocked-on-I/O — is the skeleton everything else hangs on.
- "Limited Direct Execution" is the load-bearing chapter. It answers "how does the OS stay in control if the process is running directly on the CPU?" The answer — the CPU runs user code directly for speed, but a timer interrupt periodically returns control to the kernel — is the whole trick of time-sharing. Read it carefully; it ties directly to last course's interrupts.
- The Process API interlude (
fork,exec,wait) — read it now for orientation; you'll use these in the shell capstone.forkis famously strange (it returns twice); don't fully digest it here, just meet it. Lesson 5 and the project revisit it. - Skip on first pass: the deep scheduling policy details (that's lesson 2) and the specifics of trap tables. Get the process abstraction and the control-transfer mechanism solid first.
Explain it back #
Explain to a colleague why user programs can't just directly read from the disk or remap memory themselves — why they have to make a system call. A strong answer names the kernel/user-space privilege split (user code runs unprivileged and can't execute hardware-touching instructions) and the reason it exists (isolation and safety — an untrusted or buggy program must not be able to corrupt the machine or other processes). Bonus: connect the syscall boundary to a validated-API or sandbox pattern in your own work.
Where this connects #
Backward: Last course's interrupts (a context switch is the interrupt save/restore mechanism, now used to switch processes) and virtual memory (per-process page tables are what make process isolation safe). The "save state, switch, restore" dance you met for I/O is the beating heart of multitasking.
Forward: Lesson 2 asks the question this lesson raises — when the kernel switches, which process does it pick? That's scheduling. Lesson 3 (IPC) is how these isolated processes talk to each other despite the isolation. And the whole course builds toward the Unix-shell capstone, where you'll fork, exec, and wait on real processes — the API you just met made concrete.
That's the free preview. Sign in to continue this course.
Sign in to continueNew here? Make a desk →