Last updated: 2026-09-18

U
Undergraduate level

Operating Systems Fundamentals

An operating system is easy to describe too narrowly as "the thing that runs your programs." Its real job is resource abstraction and arbitration: many programs want to use one CPU, one pool of memory, and one set of disks and devices, and the OS is the layer that gives each program the illusion of having those resources to itself, while actually sharing them out safely underneath. Silberschatz, Galvin, and Gagne's textbook is the standard reference for this material1.

The Process Lifecycle

A process is a running program together with everything it needs to keep running — its own memory space, its own set of open files, its own register values when it's not currently executing. Every process moves through a well-defined set of states over its lifetime:

stateDiagram-v2 [*] --> New New --> Ready: admitted Ready --> Running: scheduler dispatches Running --> Ready: interrupt / time slice expires Running --> Waiting: I/O or event wait Waiting --> Ready: I/O or event completes Running --> Terminated: exit Terminated --> [*]

The distinction between Ready and Waiting matters more than it looks: a Ready process could run right now if the CPU were free — it's only waiting for the CPU itself — while a Waiting process couldn't run even if given the CPU immediately, because it's blocked on something external (disk I/O completing, a network response arriving). Confusing the two is a common source of bugs when reasoning about concurrency: a process stuck in Waiting isn't "slow," it's specifically blocked on a named event, and finding that event is the actual debugging question.

CPU Scheduling Algorithms

Whenever more than one process is Ready, the scheduler decides which one actually gets the CPU next. Different algorithms optimise for different things:

Algorithm Rule Trade-off
FCFS (First-Come, First-Served) Run processes in arrival order Simple and fair by arrival time, but one long process delays every process behind it (the "convoy effect")
SJF (Shortest Job First) Run whichever Ready process needs the least CPU time Provably minimises average waiting time, but requires knowing run times in advance and can starve long jobs indefinitely
SRTF (Shortest Remaining Time First) Pre-emptive version of SJF — switches if a newly-arrived job is shorter than what's left of the current one Even better average waiting time than SJF, at the cost of more context switches
Priority Run the highest-priority Ready process Lets important work jump the queue, but can starve low-priority processes without an ageing mechanism
Round-Robin Give each Ready process a fixed time slice, then move to the next Fair and responsive (no process waits arbitrarily long), but shorter time slices mean more context-switch overhead

Round-robin is the clearest illustration of the throughput-versus-fairness trade-off other scheduling algorithms also face: a small time slice makes the system feel responsive because no process waits long for its turn, but every switch between processes has a real cost (saving and restoring registers, refilling the cache with the new process's data), so shrinking the time slice too far spends more total CPU time context-switching than doing useful work — the fairness FCFS/SJF/SRTF give up is exactly the throughput round-robin trades away to get it.

Memory Management: Paging and Segmentation

A process needs to believe it has a large, contiguous block of memory to itself, while in reality many processes share the same physical RAM. Segmentation divides a process's memory into logical, variable-sized segments (code, stack, heap), each mapped somewhere in physical memory — but because segments vary in size, freeing and reallocating them over time leaves scattered, unusable gaps between surviving segments, called external fragmentation, even when the total free memory would be enough if it weren't split into so many small pieces.

Paging takes a different approach: physical memory is divided into fixed-size frames, and a process's memory into same-sized pages, with a page table recording which frame each page currently lives in. Because every frame is the same fixed size, there's no external fragmentation — any free frame can hold any page — at the cost of internal fragmentation instead: a page that doesn't need its full frame's worth of space still occupies the whole frame, wasting whatever's left over. Trading external fragmentation (unusable gaps of arbitrary, hard-to-predict size) for internal fragmentation (wasted space bounded by, at most, one frame per page) is, in practice, usually the better trade, which is why paging is the dominant approach in modern operating systems. Denning's early survey of virtual memory is the source most later textbook treatments of paging trace back to, and it's worth reading for a reason beyond history: it covers the observation that a running process only actively needs a small, slowly-changing subset of its total pages at any moment — the working set — and that observation is still the justification for why paging works well in practice rather than just in principle2.

File Systems and I/O

The file system gives processes a stable, named abstraction (files and directories) over the raw block-addressed storage a disk actually provides underneath. I/O more broadly is split between block devices (disks — addressed and transferred in fixed-size chunks, and randomly seekable) and character devices (keyboards, serial ports — addressed as a stream, one unit at a time). Waiting for I/O to complete can be handled by polling (repeatedly checking if the device is ready — simple but wastes CPU cycles busy-waiting), interrupts (the device signals the CPU when it's ready, freeing the CPU to do other work in the meantime), or DMA (Direct Memory Access — the device transfers data directly to/from memory without the CPU copying each byte itself, freeing the CPU almost entirely from the transfer once it's initiated).

References


  1. Silberschatz, A., Galvin, P. B., & Gagne, G. (2019). Operating System Concepts (Global ed., 10th ed.). Wiley. Held by the University of Reading Library.

  2. Denning, P. J. (1970). Virtual memory. ACM Computing Surveys, 2(3), 153–189. https://doi.org/10.1145/356571.356573