Chapter 16

Operating Systems

College
At a glance
Core ideaThe OS shares scarce hardware safely among untrusting programs.
Key termProcess & context switch — the illusion of running many at once.
You can…Compare scheduling policies like FCFS vs Round Robin.
Watch outShared data across threads breeds race conditions and deadlock.
Theory

An operating system (OS) is the software layer between hardware and applications. It is a resource manager and a referee, providing three great abstractions so that programs need not touch raw hardware: the process (a running program), virtual memory (each process sees its own private address space), and the file (a named, persistent stream of bytes).

Because there are more processes than CPU cores, the OS scheduler rapidly switches the CPU between processes — a context switch saves one process's state and restores another's — creating the illusion of simultaneous execution (concurrency). Virtual memory, via paging, gives every process a clean, contiguous-looking address space that the hardware's MMU maps to scattered physical RAM (and to disk when RAM is full).

The OS runs privileged code in kernel mode and applications in restricted user mode; a program requests OS services through a system call, the controlled gateway across that boundary. This protection is what stops one buggy app from crashing the whole machine or reading another's memory.

Explanation

The unifying job of an OS is sharing scarce resources safely and fairly among untrusting programs. Time-sharing the CPU gives responsiveness; space-sharing memory with isolation gives security; mediating I/O gives a uniform interface to wildly different devices. Every OS feature is a variation on "many want this resource; grant access without letting them corrupt each other."

Concurrency is powerful but perilous. When multiple threads touch shared data, their operations can interleave badly — a race condition — producing wrong results that appear only sometimes. The fix is synchronisation (locks, mutexes, semaphores) to enforce mutual exclusion over a critical section. But locks introduce their own hazard, deadlock: two threads each holding a lock the other needs, both waiting forever. Managing this tension is among the hardest parts of systems programming.

Why virtual memory matters. It lets programs use more memory than physically exists, isolates processes from one another, and frees programmers from ever knowing which physical RAM addresses they occupy — the OS and hardware translate transparently.

Practical

We simulate a scheduler running two well-known policies — FCFS (first-come-first-served) and Round Robin (time-sliced) — and compare the average wait, illustrating why time-slicing improves responsiveness.

# Each process: (name, burst) = CPU time it needs.
jobs = [("A", 6), ("B", 2), ("C", 4)]

def fcfs(jobs):
    """Run each job to completion in arrival order. Simple but poor for short jobs."""
    time, waits = 0, {}
    for name, burst in jobs:
        waits[name] = time          # this job waited for all prior jobs
        time += burst
    return waits

def round_robin(jobs, quantum=2):
    """Give each job a fixed time slice, cycling until all finish -> fair, responsive."""
    from collections import deque
    remaining = deque((name, burst) for name, burst in jobs)
    time, finish = 0, {}
    while remaining:
        name, burst = remaining.popleft()
        run = min(quantum, burst)   # run for at most one quantum
        time += run
        burst -= run
        if burst == 0:
            finish[name] = time     # completed
        else:
            remaining.append((name, burst))   # not done -> back of the queue
    return finish

print("FCFS waits:      ", fcfs(jobs))
# {'A': 0, 'B': 6, 'C': 8}  -> short job B waits 6 behind the long job A

print("Round Robin done:", round_robin(jobs))
# {'B': 4, 'C': 10, 'A': 12} -> B finishes early; no job monopolises the CPU

Under FCFS the short job B is stuck behind the long job A (the "convoy effect"). Round Robin slices time so B finishes quickly and no process hogs the CPU — the essence of an interactive, responsive system. The cost is extra context switches, the eternal scheduling trade-off.

Q&A
Q1 What is the difference between a process and a thread?

A process is an independent running program with its own private memory space. A thread is a lightweight unit of execution within a process; threads of one process share its memory. Threads are cheaper to create and communicate faster (shared memory), but that sharing is exactly what makes race conditions possible — separate processes are isolated and safer but heavier.

Q2 What is a race condition, concretely?

When two threads do balance = balance + 1 at once, each may read the same old value (say 10), add one, and write 11 — so two increments produce 11 instead of 12. The outcome depends on the exact interleaving of their steps, which is why race bugs are intermittent and maddening. A lock around the update forces the operations to happen one at a time.

Q3 Why do we need both kernel mode and user mode?

For protection. Privileged operations — accessing hardware, changing memory maps, halting the CPU — run only in kernel mode. Applications run in user mode and cannot execute those instructions directly; they must ask via a system call, which the kernel validates. This boundary stops a buggy or malicious program from taking over the machine or reading other programs' data.

Q4 What is a deadlock and how is it avoided?

Deadlock is a standstill where each thread holds a resource another needs and none can proceed — like two people each gripping one of two forks, each waiting for the other. It requires four simultaneous conditions (mutual exclusion, hold-and-wait, no preemption, circular wait). Break any one — e.g. always acquire locks in a fixed global order to prevent the circular wait — and deadlock becomes impossible.

Concept mind map

How the ideas connect

Every key idea in this chapter, branching from the core concept — use it to see the whole picture at a glance.

processcontext switchschedulerFCFSRound Robinshared hardwareOperating systems
Infographic

The key facts, visualised

Process
A running program with its own memory and state.
Context switch
Saving one process state and loading another to share the CPU.
FCFS
First-come first-served: run jobs in arrival order, no preemption.
Round Robin
Give each process a fixed time slice in turn.
Solved examples

Worked problems, step by step

Follow each solution line by line, then try to reproduce it on paper before moving on.

Example 1Jobs A(4ms), B(2ms), C(1ms) arrive in that order under FCFS. Give completion order and finish times.

  1. Run A: finishes at 4.
  2. Then B: finishes at 6.
  3. Then C: finishes at 7.

Example 2Two processes share a CPU with Round Robin and a 10ms slice. What happens after P1 uses its slice?

  1. P1 runs 10ms then its slice ends.
  2. The OS context-switches to P2.
Practice problem set

Now you try

Work each one out first, then tap to reveal the worked answer.

1What is a process?
An instance of a running program with its own memory, registers, and execution state.
2What is a context switch?
Saving the state of one process and restoring another so the CPU can be shared, giving the illusion of concurrency.
3What does an OS scheduler decide?
Which ready process runs next on the CPU and for how long.
4How does FCFS differ from Round Robin?
FCFS runs each job to completion in arrival order; Round Robin gives each a fixed time slice in turn.
5What problem can FCFS cause?
A long job at the front makes short jobs wait a long time (the convoy effect).
6Why does the OS mediate access to hardware?
To share scarce resources safely and protect programs from interfering with each other.