Notes
All notes

Operating Systems: processes, threads and context switches

These are revision notes for the “processes and threads” part of an OS course. The question blocks are things worth being able to answer out loud; the solution blocks stay hidden until you tap Show, so you can test yourself before reading the answer.

What a process actually is

A process is a program in execution. The program on disk is just bytes; a process is that code plus everything the CPU needs to run it:

Two runs of the same program are two different processes with separate address spaces. That isolation is the point: one process cannot scribble over another’s memory without the OS’s help.

QQuestionWhy does each process need its own address space?
ASolution

So a bug or a malicious process cannot read or corrupt another process’s memory. The OS maps each process’s virtual addresses to physical frames, so the same virtual address means different physical memory in different processes.

The process control block (PCB)

The OS keeps one PCB per process. When the CPU is taken away, the process’s entire machine state is saved here; when it is scheduled again, that state is restored.

QQuestionWhat lives in a PCB?
ASolution

Everything needed to suspend and resume the process:

  • process id and current state,
  • program counter, stack pointer and general-purpose registers,
  • memory-management information (page tables, base/limit),
  • scheduling priority and accounting,
  • open file descriptors, I/O status and signals.

Process states

A process is always in exactly one of five states, and the OS moves it between them:

\begin{tikzpicture}[
  st/.style={draw,thick,rounded corners,minimum width=2.1cm,minimum height=0.9cm,font=\small},
  a/.style={->,thick},
  l/.style={font=\scriptsize,text=black!70}
]
  \node[st] (new) at (0,0) {New};
  \node[st] (ready) at (3.2,0) {Ready};
  \node[st] (run) at (6.4,0) {Running};
  \node[st] (wait) at (3.2,-2) {Waiting};
  \node[st] (term) at (9.6,0) {Terminated};

  \draw[a] (new) -- node[l,above]{admit} (ready);
  \draw[a] (ready) -- node[l,above]{dispatch} (run);
  \draw[a] (run.north) to[bend right=40] node[l,above]{preempt} (ready.north);
  \draw[a] (run) -- node[l,above]{exit} (term);
  \draw[a] (run.south) -- (6.4,-2) -- (wait.east);
  \node[l] at (5.35,-1.9) {wait};
  \draw[a] (wait.north) -- node[l,left]{I/O done} (ready.south);
\end{tikzpicture}

The distinction between Ready and Waiting is the one people get wrong: Ready means “wants the CPU”, Waiting means “does not want the CPU yet”.

QQuestionRunning → Ready and Running → Waiting both take the CPU away. What is the difference?
ASolution

In Ready the process is runnable and only lacks a CPU; it will run again as soon as it is scheduled. In Waiting it is blocked on an external event and cannot use a CPU even if you gave it one. Only the event (I/O completion, signal, lock release) can move it back to Ready.

Context switching

A context switch is saving the running process’s state into its PCB and loading the next process’s state from its PCB. It is pure overhead — no useful work happens — which is why the time slice cannot be made too small.

QQuestionWhy is a context switch more expensive than an ordinary function call?
ASolution

A function call saves a handful of registers by convention. A context switch:

  • saves and restores the entire register set and program counter,
  • switches the address space, which can flush the TLB,
  • invalidates cache locality — the new process’s data is cold,
  • and runs scheduler bookkeeping.

The direct cost is hundreds to thousands of cycles; the indirect cost from cold caches and a flushed TLB is often larger.

Threads vs processes

A thread is the unit of scheduling; a process is the unit of resource ownership. Threads in one process share its address space, heap and open files, but each has its own stack, registers and program counter.

Process Thread
Address space own shared with siblings
Create / switch cost high low
Isolation strong none between threads
Communication IPC (pipes, sockets, shared memory) shared memory directly
Crash impact contained can take down the whole process
QQuestionWhy does every thread still need its own stack?
ASolution

The stack holds the call chain — return addresses, local variables and arguments. Threads run different code at different points, so they cannot share one call chain. Registers are saved per thread too, but the stack is the big per-thread allocation.

Check yourself

Try these before revealing the answers.

QQuestionCan two threads in the same process run on two CPUs at once?
ASolution

Yes. Threads are the scheduling unit, so a multi-core CPU can run several threads of one process in parallel. A single-threaded process is limited to one core.

QQuestionWhat does fork() return, and why is it different in the two processes?
ASolution

It returns the child’s PID in the parent and 0 in the child (and -1 on failure). The child needs to know it is the child, and 0 is the natural way to say “you are the new process”; the parent needs the child’s PID to wait on it or signal it.

QQuestionWhat is a zombie process?
ASolution

A process that has terminated but whose exit status has not yet been read by its parent. The PCB entry lingers so the parent can call wait(). If the parent never does, the entry leaks until the parent exits (then it is reaped by init).

QQuestionWhy is switching threads cheaper than switching processes?
ASolution

Threads of one process share an address space, so the switch avoids changing page tables and flushing the TLB. You still save the registers and stack pointer, but you skip the expensive memory-management work.

QQuestionA process is blocked reading a file. Is it using the CPU?
ASolution

No. It is in the Waiting state and has been removed from the run queue. The disk controller interrupts when the read completes, which moves it back to Ready.

Common pitfalls