What Is a Process?
A process is an executing program. Not the program code on disk — but that code loaded into memory, running, with its own state and identity. Every time you open a browser tab, run a terminal command, or start a database server, you are creating a process.
What the Kernel Tracks: The Process Control Block
The kernel maintains a Process Control Block (PCB) for every process. It stores everything needed to pause and resume a process:
| Field | Purpose |
|---|---|
| PID | Process ID — a unique number identifying this process |
| State | new, ready, running, waiting, terminated |
| Registers | CPU register values (saved when the process is paused) |
| Program counter | Which instruction to execute next |
| Memory management | Page tables, memory map |
| File descriptors | Open files, network sockets |
| Scheduling info | Priority, time slice, CPU time used |
The Five Process States
- New — The process is being created (e.g., right after
fork()). - Ready — The process is loaded into memory and waiting for the CPU. It is eligible to run.
- Running — The CPU is executing the process's instructions. Only one process per core can be running at any time.
- Waiting (Blocked) — The process is paused, waiting for an event (I/O completion, a signal, a child to exit).
- Terminated — The process has finished (via
exit()) or been killed. Its resources are being reclaimed.
Transitions:
- New → Ready (kernel finishes setup)
- Ready → Running (scheduler picks it)
- Running → Ready (time slice expired, preempted)
- Running → Waiting (I/O request made)
- Waiting → Ready (I/O completed)
- Running → Terminated (exit)
See the full lifecycle in action.
Context Switching
A context switch is when the kernel saves the current process's state (registers, program counter, memory mappings) and restores a different process's state. Each context switch costs thousands of CPU cycles — saving/restoring registers, flushing the TLB, invalidating caches. This is a key cost of multitasking.
Process Creation
On Unix, a new process is created by the fork() system call, which creates a copy of the calling process. The child then typically calls exec() to replace its memory image with a new program. This two-step process — copy, then replace — is why Unix shells can run any command.
Learn how system calls cross the kernel boundary.
This article is part of the Operating Systems From the Ground Up learning path.