In this lecture we view the many different, unique yet important perspectives of different portions of the OS and hardware to answer the most important question about our OSs, what is a process?
Lecture Date
📅 February 18, 2026
Standard
CPU
Topics Covered
Process Control BlockProcess Address SpaceProcess StateInter-Process CommunicationContext Switching
Interrupts — How the outside world gets the CPU's attention
Here's the complete CPU we built — every component will matter today:
Our Complete CPU from LN8
Now that we know the hardware, today's question is: what does it feel like to run a program on it?
Today's Agenda
What Is a Process? — The philosophical framing
The OS View — PCB Process Control Block
The Memory View — PAS Process Address Space
The CPU View — PEC Process Execution Context
The Scheduler View — State Process state transitions
The IPC View — IPC Inter-Process Communication
The Hierarchy View — Hierarchy Process relationships
The Security View — Security Privilege enforcement
Context Switching Revisited — With our new vocabulary
Exploring Processes in Linux — Hands-on tools
💡 Key Theme: A process means something different to every component of the system. Each "manager" sees a different slice. To truly understand processes, you must learn to shift between these perspectives.
Throughout this lecture, we'll color-code terminology by which manager uses it:
But that definition only scratches the surface. To really understand what a process is, let's ask: what does the CPU "feel" when a program runs?
The registers feel values being created, mutated, and moved as computation progresses
The ALU feels operations being demanded — "add these two numbers," "compare these values"
The Control Unit feels data movement, control flow decisions, and communication in and out of the CPU
The interrupt hardware feels the outside world altering the CPU's attention
In much the same way that biology tries to rationalize emotion, memory, and experience as a series of chemical reactions in our sensory systems and neurons, the execution of a program is best understood by reflecting on the machine that is running it.
A process, then, is not a single thing you can point to. It's a nebulous set of management tasks completed over a given time frame by multiple cooperating subsystems. No single component "is" the process — the process is the coordination of all of them.
🍽️ The Restaurant Metaphor: Your experience at a restaurant is the combined work of the host (who seats you), the waiter (who takes your order), the chef (who cooks your food), the bartender (who makes your drink), and the manager (who ensures everything runs smoothly). No single person "is" your dining experience — it's the coordination of all of them. And each person sees your visit differently. Keep this analogy in mind as we examine each "manager" of a process.
📚 Historical Note — The Origin of "Process": The term "process" was coined by the designers of Multics in the 1960s. Before that, the concept was simply "job" (from batch processing). The shift from "job" to "process" reflected the move from sequential batch execution to interactive time-sharing — processes could be paused, resumed, and share the machine. This maps directly to the OS history we covered in LN6.
The OS General View: The Process Control Block (PCB)
At the most general level, the OS views each process as a PCB — a data structure that stores everything needed to manage this process relative to all the others.
Think of it as the OS's "customer file" for each process. It doesn't contain the program itself — just the metadata needed for management.
Process Control Block
PCB
Process ID (PID)4827
Process Namemy_program
StateRUNNING
Program Counter0x00401A3C
CPU Registers (saved)
RAXRBXRCXRDXRSIRDIRSPRBP
Memory InfoPage Table Ptr
Open Files3 handles
PriorityNormal (20)
What's Inside a PCB?
Field
Purpose
Manager That Uses It
PID
Unique process identifier
OS, Scheduler, Security
Process State
Running, Ready, Blocked, Terminated
Scheduler
Program Counter
Current instruction address (copy from CPU)
OS and CPU
CPU Registers
Saved register snapshot
CPU (via context switch)
Memory Info
Base/limit registers, page tables
Memory hardware (MMU)
I/O Status
Open files, network connections, devices
I/O subsystem
Scheduling Info
Priority, execution history, time slice
Scheduler
Notice how the PCB references data from multiple other managers. It's the central coordination point — the "master file" that ties everything together.
What's NOT in the PCB?
The entire program is not stored in the PCB. Think of it like this: your picture ID, social security number, bank statements, and social media profile are all interesting — but the chef making your food doesn't need any of that. They only need your name and order. Maybe allergy information if it helps prepare your food safely.
The PCB stores only what's relevant to managing this process compared to other processes. More information is only useful if it helps make better decisions about how to distribute limited resources.
The PCB is essentially a large struct containing other structs or basic types — each storing information relevant to a different management concern.
📚 Historical Note — Multics PCB Bottleneck: Multics (1965) was among the first systems to formalize the PCB concept. But their process table grew so large it became a performance bottleneck — every context switch required traversing it. This taught the field that management overhead must scale carefully. Sound familiar? It's Amdahl's Law from LN7: the serial overhead of management can cap your system's performance, no matter how fast your hardware gets.
The Memory View: The Process Address Space (PAS)
To the memory hardware, a process looks like nothing more than a chunk of address space to organize. The PAS is the sandbox of memory allocated exclusively to one process — no other process can see or touch it.
The Four Segments
Segment
Contents
Behavior
Text (Code)
Compiled machine instructions
Fixed at load time, read-only
Static (Data)
Globals, constants, library links
Fixed at load time
Stack
Function call frames, local variables
Grows downward with each function call
Heap
Dynamic allocations
Grows upward as memory is requested
The restaurant analogy: a dining table only provides a place to sit. It doesn't take your order, cook your food, or check your ID. Memory hardware is the same — it only organizes where processes live. Nothing more.
💡 Cross-Manager Connection: The Stack Pointer (SP) register in the CPU points directly into the Stack segment of the PAS. This is where the CPU and memory views connect — the CPU's register holds an address in the process's memory sandbox.
Where Rust Lives in the PAS
static GLOBAL: i32 = 42; // Static segmentconst PI: f64 = 3.14159; // Static segment (may be inlined)fnmain() { // Text segment (compiled code)letlocal = 10; // Stackletboxed = Box::new(20); // Heap (pointer on stack, data on heap)letname = String::from("hi"); // Heap (String data) + Stack (metadata)
}
Management is about delegating the right tasks to the right tools. The memory subsystem's job is simple: provide organized space. Just as a restaurant dining table isn't responsible for taking your order, the PAS isn't responsible for scheduling or security.
The CPU View: The Process Execution Context (PEC)
The CPU doesn't care about scheduling, memory layout, or security policies. It needs exactly one thing: enough state to execute the next instruction. That minimal state is the PEC.
What's in the PEC?
Field
CPU Component It Drives
Program Counter (PC)
Tells the CU what instruction to fetch next
CPU Registers
Operand values for the ALU
Stack Pointer (SP)
Points into the PAS stack for function calls
Flags/Status Register
Condition codes from the last ALU operation
The Same Data, Different Decisions
Here's a crucial insight: both the OS and the CPU see the same Program Counter, but they use it to make completely different decisions:
Who
Sees
Decides
CPU
PC = 0x00401A3C
"Fetch the instruction at this address, decode it, set up the ALU"
OS
PC = 0x00401A3C
"This process is mid-execution. Should I let it continue or switch to another?"
Same data. Different context. Different decisions.
🍽️ Restaurant Analogy: The chef and the manager both see the same food item on an order ticket. The chef uses it to direct the kitchen: "Set up station 3, prep the salmon." The manager uses it to make business decisions: "This customer ordered the special — maybe offer a dessert discount to encourage a return visit." Same information, different concerns.
💡 Cross-Manager Connection: The PCB stores a copy of the PEC — this duplication is the cost of context switching. Every time the OS switches processes, it must save the entire PEC into the PCB and load a new one. Faster context switches = less data to copy.
The Scheduler View: Process State
The scheduler doesn't worry about memory, computations, or hardware details. It needs to answer one question: what state is this process in, so we can decide whether to give it the CPU?
Let's "zoom in" on the state field of the PCB.
Process State Diagram
Click a transition arrow to see what triggers it.
The Five States
State
Meaning
New
Process is being created
Ready
Can run — waiting for CPU time
Running
Currently executing on the CPU
Blocked
Waiting for an external event (I/O, signal)
Terminated
Finished — resources can be reclaimed
Transition Triggers
Each arrow in the state diagram identifies a crucial moment the scheduler must handle:
Transition
Trigger
What Happens
New → Ready
Process created
New PCB, new PAS, new PEC allocated
Ready → Running
Dispatched to CPU
PEC loaded onto hardware, PAS activated
Running → Blocked
I/O wait
Computation could proceed but data hasn't arrived
Blocked → Ready
I/O complete
Requested data arrived — ready to resume
Running → Ready
Interrupt
Preempted — could continue but something urgent came up
Running → Terminated
Exit
Process completed — PCB, PAS, PEC reclaimed
💡 Cross-Manager Connection: The scheduler's Blocked state is triggered by I/O operations that the PCB's I/O status field tracks. When the I/O subsystem signals completion, the PCB is updated and the scheduler transitions the process to Ready.
Notice how the scheduler's view is intentionally simplified. A more complex set of states could enable more nuanced decisions, but at a higher management level all that detail boils down to these five states. Abstraction at work!
The IPC View: Inter-Process Communication
The OS creates an illusion of isolation — every process "thinks" it's running alone on the machine. So how does any process become aware of any other?
By explicitly engaging with another by name. IPC breaks through the isolation deliberately.
IPC Mechanisms
Mechanism
Direction
Description
Restaurant Analogy
Pipes
Unidirectional
One process writes, another reads
Passing a note one way
Message Queues
Bidirectional
Structured messages between processes
Having a conversation via the waiter
Shared Memory
Direct
Processes share a memory region
Pushing tables together (breaks isolation!)
Sockets
Network/local
Communication across machines
Calling someone on the phone
Shared memory is the fastest but most dangerous — it forces the closure of the illusion of isolation and requires careful synchronization. Remember LN7's synchronization concern? This is exactly where it applies.
Rust Channels as Pipes
use std::sync::mpsc;
use std::thread;
fnmain() {
let (sender, receiver) = mpsc::channel();
thread::spawn(move || {
sender.send("Hello from another thread!").unwrap();
});
letmessage = receiver.recv().unwrap();
println!("Received: {}", message);
}
💡 Cross-Manager Connection:Security determines whichIPC mechanisms a process can use. A user-mode process can't just write to another process's memory — it must use sanctioned channels that the kernel mediates.
The Hierarchy View: Related Processes
How do processes know if they're related to one another? This is where UNIX and Windows take fundamentally different approaches.
UNIX: The Fork Tree
In classic UNIX-style systems, new processes are typically created through fork() followed by exec(). Every process has one parent, forming a tree rooted at a system init process.
Loading graph...
Windows: The Disconnected Graph
In Windows, processes are created from scratch via CreateProcess(). Relationships require explicit consent via handles. The result is a disconnected graph — processes that want to relate must opt in.
Loading graph...
Comparison
Aspect
UNIX
Windows
Creation
fork() — clone parent
CreateProcess() — from scratch
Structure
Strong parent/child tree model
Weaker tree emphasis; many relations are handle-based
Relationships
Implicit (parent-child)
Explicit (handles, consent)
Finding processes
Parent/child traversal is natural
Usually OS enumeration APIs, with handle relationships as extra structure
Trade-off
Needs security for malformed connections
More isolation but harder discovery
Rust Process Spawning
use std::process::Command;
letchild = Command::new("ls")
.arg("-la")
.spawn()
.expect("Failed to spawn child process");
letoutput = child.wait_with_output().unwrap();
println!("Child exited with: {}", output.status);
Rust's Command API abstracts over both models — on UNIX it performs fork() + exec(), on Windows it calls CreateProcess().
💀 The Fork Bomb::(){ :|:& };: — a Bash one-liner where a function recursively forks itself, consuming all available PIDs and crashing the system. This is why process limits (ulimit) exist. The tree structure makes it easy to kill an entire subtree when a fork bomb is detected.
The Security View: Privilege Enforcement
The bouncer at the club: doesn't care what goes on inside, only who is allowed in and what they're allowed to do.
Security checks whether a process has kernel or user-level access, alerting the OS to block operations the process shouldn't perform. The system call API is the only gateway.
User Mode vs Kernel Mode System Calls
User Mode (Ring 3)
What It Requests
Kernel Implementation
fork()
Create a subprocess
do_fork() — allocates new PCB, PAS, PEC
open()
Open a file
Kernel driver accesses device hardware directly
read() / write()
File I/O
DMA transfer, buffer management
exit()
Terminate self
do_exit() — reclaims PCB, PAS, PEC
Each user-available call is backed by kernel-level code that has full hardware access and carries out the request on behalf of the user process. The user process never touches hardware directly.
💡 Cross-Manager Connection: When fork() is called, every manager is involved:
PCB: A new PCB is allocated with a fresh PID
PAS: A new address space is created (copy-on-write from parent)
PEC: A new execution context is initialized
Scheduler: The new process enters the Ready state
Hierarchy: A parent-child link is established
Security: The child inherits the parent's privilege level
This is why fork() is one of the most complex system calls — it touches every subsystem.
💀 The Dirty COW Vulnerability (2016): A race condition in the Linux kernel's copy-on-write mechanism (used by fork()) allowed unprivileged users to gain write access to read-only memory mappings, achieving root privilege escalation. It existed in the kernel for 9 years before discovery (CVE-2016-5195). This vulnerability directly connects fork, memory, and security — a bug in one manager's implementation broke the guarantees of another.
The Big Picture: Every Manager's Perspective
Let's step back and see how each manager views the same process:
Manager
Sees
Key Concern
OS (PCB)
A struct of management metadata
Coordinating all other managers
Memory (PAS)
Four segments: text, static, stack, heap
Where to organize the process's data
CPU (PEC)
PC, registers, SP, flags
What to execute next
Scheduler (State)
New, Ready, Running, Blocked, Terminated
When to give/take CPU time
IPC
Pipes, queues, shared memory, sockets
How processes communicate
Hierarchy
Parent-child tree (UNIX) or graph (Windows)
Who is related to whom
Security
Ring 0 / Ring 3, syscall permissions
What is allowed
Your living, breathing experience at a restaurant — or at Disneyland, or a movie theatre — is reflected in all the different jobs that had to be completed by different people or machines to make the whole event happen. Our OS is doing exactly the same thing for each running process.
Context Switching Revisited
With our new vocabulary, let's restate the context switch in precise terms. We first saw this in LN6 — now we understand every piece of it at the hardware level.
The Steps
Step 0 — Interrupt Received:
A hardware interrupt (timer, device) or software trap (syscall) arrives at the CPU.
Step 1 — Save Current PEC to PCB:
The quicksave. The Program Counter, registers, Stack Pointer, and flags are copied from the CPU into the current process's PCB.
Step 2 — Scheduler Selects Next PCB:
The OS calls the scheduler, which searches the process table for a PCB with state = Ready.
Step 3 — Restore New PEC from PCB:
The quickload. The selected process's PEC is loaded into the CPU hardware. The PCB state is updated to Running. The PAS is switched (page tables updated in the MMU).
Step 4 — Resume Execution:
The CPU continues from the new process's Program Counter as if nothing happened.
Context Switch Animation
CPU
Process Arunning
PCB A
Process Bready
PCB B
Running Process A
Process A is executing on the CPU
Context switch overhead: ~1,000-10,000 CPU cycles
Context Switch
Running Process A
Process A is mapped to the real hardware and executing
Real Hardware
Overhead:
~1K-10K cycles
↑Maps to
Process A●
On hardware
Process B
Waiting
🤔 How do we decide when to context switch and which process to run next? That's the scheduling problem — and it's the entire focus of LN10!
Exploring Processes in Linux
Let's ground all this theory in observable reality. Linux exposes process information through several powerful tools.
The /proc Filesystem
Linux represents every process as a directory under /proc. Each directory is named by PID:
# See your own process's status (the PCB in text form!)cat /proc/self/status
# See the memory map (the PAS segments!)cat /proc/self/maps
# See raw process statisticscat /proc/self/stat
The /proc/self/maps output directly shows the text, stack, heap, and library segments we discussed — memory addresses and all.
Process Listing and Trees
# List all processes with state, CPU%, memory%
ps aux
# Visualize the UNIX process tree (Section 7!)
pstree
# Real-time process monitoring (interactive)
top
htop # More colorful version
pstree directly visualizes the fork tree we discussed — you'll see init (or systemd) at the root with everything branching out.
Tracing System Calls
# Per-process CPU statistics
pidstat 1
# Trace every system call a process makes (Security section!)
strace ls -la
strace is revelatory — it shows every syscall a process makes in real time. You'll see open(), read(), write(), mmap(), brk() — all the kernel gateways we discussed. Try it on a simple command and watch the system call API in action.
Summary
Concept
Key Point
Process
Running execution of a program — coordinated across multiple managers
The running execution of a program, managed across multiple subsystems
PCB
Process Control Block — OS metadata struct for managing a process
PAS
Process Address Space — isolated memory sandbox (text, static, stack, heap)
PEC
Process Execution Context — minimal CPU state (PC, registers, SP, flags)
Process State
New, Ready, Running, Blocked, or Terminated
IPC
Inter-Process Communication — pipes, queues, shared memory, sockets
Context Switch
Save current PEC to PCB, select new PCB, load new PEC
System Call
The controlled gateway from user mode to kernel functionality
Manager Perspectives:
OS (PCB) → Management metadata for coordination
Memory (PAS) → Where to organize data (text, static, stack, heap)
CPU (PEC) → What to execute next (PC, registers, SP, flags)
Scheduler → When to give/take CPU time (state transitions)
IPC → How processes communicate (pipes, shared memory, sockets)
Hierarchy → Who is related (UNIX tree vs Windows graph)
Security → What is allowed (Ring 0/3, syscall permissions)
Context Switch Steps:
0. Interrupt received (timer, syscall, device)
1. Save PEC → PCB (quicksave)
2. Scheduler selects next Ready PCB
3. Load PCB → PEC (quickload), update state to Running
4. Resume execution at new PC