Ran Wei/CS Series/10
中文
Computer Science Fundamentals — Ran Wei

Module 10: Operating systems

Understand processes, threads, scheduling, virtual memory and files. Reproduce a lost update deliberately and repair it with a lock.

≈ 5 hours4 sessions2 labs8 exercises6 quiz questions

By the end you can

  • Distinguish processes and threads.
  • Compare scheduling objectives.
  • Explain address translation.
  • Use scoped file operations.
  • Identify and protect critical sections.

Before you start

Recommended modules: 03, 09.

Know program state and memory. The labs run a short child process, create temporary files and join finite worker threads.

Contents

Study plan

5 hours

Four 75-minute sessions including practice. Allow longer for extensions or unfamiliar prerequisites. Progress is saved locally and shared between language editions.

Session 175 min
Concepts and worked examples
Session 375 min
Apply and extend
1

Processes and threads

A process is an executing program with resources and an address-space context. Threads within a process share memory but have separate execution state and stacks. Separate processes usually isolate ordinary memory; communication needs pipes, sockets or explicitly shared facilities. A process may be ready, running or blocked waiting for I/O. A program file is passive; multiple processes can execute that same file. Thread concurrency does not imply simultaneous CPU execution, and interpreter-specific constraints should not be confused with operating-system guarantees.

Check your understanding

Do two threads in one process share all stack frames?

Worked solution

No; their execution stacks are separate, while shared objects may be accessed by both.

2

Scheduling and context switching

A scheduler chooses ready work. First-come-first-served is simple but a long job delays short jobs. Round robin rotates a time quantum among ready tasks, improving interactive response while increasing switching overhead if the quantum is tiny. Turnaround measures completion minus arrival; response measures first service minus arrival. Saving and restoring registers allows execution to resume after a context switch. Fairness, throughput and latency are different objectives; a policy cannot be judged without its workload and goal.

Check your understanding

Is response time identical to turnaround time?

Worked solution

No; a job may start quickly but finish much later.

3

Virtual memory and paging

Programs use virtual addresses translated to physical storage through page mappings. A page number chooses a mapping; an offset chooses a byte within that page. With 4096-byte pages, virtual address 8197 has page 2 and offset 5. Protection and separate mappings isolate processes; a TLB caches translations. A page fault transfers control to the operating system and may allocate, load or reject access. It does not always mean a disk read. Virtual memory is an address-space abstraction, not simply extra RAM from a disk.

Check your understanding

For 1024-byte pages, split virtual address 2051.

Worked solution

Page 2, offset 3.

4

Files, handles and persistence

A file provides persistent named data; a handle tracks an open instance and its position. Close resources reliably with a context manager even after an exception. A directory organises names, while permissions govern allowed operations. Buffering means a successful write call need not imply durable storage on physical media. Applications needing crash-safe updates require explicit durability and atomicity policies. Our temporary-directory lab cleans its own files and demonstrates lifetime, not durable database transactions.

Check your understanding

Does writing to a buffer guarantee survival after power loss?

Worked solution

No; durability requires additional guarantees.

5

Race conditions, locks and deadlock

A read-modify-write operation can interleave: both threads read zero, both write one, and one increment is lost. Protect the whole critical section with a shared lock, not just its final write. Python's GIL in conventional builds is not an application-level transaction guarantee. Deadlock can arise when threads hold one resource while waiting for another in a cycle. A consistent global lock order helps prevent such cycles. The barrier lab forces a particular schedule, making the race reproducible without relying on sleeps or chance.

Check your understanding

Why is locking only the assignment insufficient?

Worked solution

The stale read may already have occurred outside the lock.

6

Common misconceptions

  • Concurrency is possible without simultaneous execution.
  • A page fault is not necessarily an error or disk operation.
7

Lab setup

Download each script and run it in a terminal with Python 3.11 or later: python m10_process.py. On Windows, py -3 is an alternative; on some systems use python3. The labs use only the standard library. Predict the result before running, then complete the variations. Run without -O so assertions remain enabled. Outputs below were captured by the builder. Code and output are identical in both language editions.

8

Lab 1 — Processes and scoped files

Check that the child has a different process ID without embedding machine-dependent IDs in the output.

Download m10_process.py

"""Observe an isolated child process and scoped file cleanup."""
import json, os, subprocess, sys, tempfile
from pathlib import Path
child = subprocess.run([sys.executable, "-c", "import os,json; print(json.dumps({'pid':os.getpid(),'answer':6*7}))"],
                       check=True, capture_output=True, text=True, timeout=10)
data = json.loads(child.stdout)
assert data["pid"] != os.getpid() and data["answer"] == 42
print("child is a different process:", data["pid"] != os.getpid())
print("child result:", data["answer"])
with tempfile.TemporaryDirectory() as folder:
    path = Path(folder) / "catalogue.txt"
    path.write_text("Dune\nFoundation\n", encoding="utf-8")
    print("file records:", path.read_text(encoding="utf-8").splitlines())
print("temporary directory removed:", not Path(folder).exists())
Captured output
child is a different process: True
child result: 42
file records: ['Dune', 'Foundation']
temporary directory removed: True
  1. Make the child exit with a nonzero code.
  2. Catch CalledProcessError at the caller.
  3. Explain why the temporary path disappears.
Worked solution

check=True converts a nonzero exit into CalledProcessError; inspect its returncode. TemporaryDirectory's context exit removes its own contents, even when control leaves through an exception.

9

Lab 2 — Force and repair a race

The barrier ensures both unsafe workers have read the old value before either writes. The safe version locks the full update.

Download m10_race.py

"""Force a lost update deterministically, then protect a critical section."""
from threading import Barrier, Lock, Thread
counter, barrier = [0], Barrier(2)
def unsafe():
    old = counter[0]
    barrier.wait(timeout=5)  # both have read zero before either writes
    counter[0] = old + 1
threads = [Thread(target=unsafe) for _ in range(2)]
for t in threads: t.start()
for t in threads: t.join(timeout=10); assert not t.is_alive()
print("forced lost update:", counter[0])
assert counter[0] == 1

counter[0] = 0
lock = Lock()
def safe():
    for _ in range(1000):
        with lock:
            counter[0] = counter[0] + 1
threads = [Thread(target=safe) for _ in range(2)]
for t in threads: t.start()
for t in threads: t.join(timeout=10); assert not t.is_alive()
print("protected updates:", counter[0])
assert counter[0] == 2000
Captured output
forced lost update: 1
protected updates: 2000
  1. Draw the forced two-thread interleaving.
  2. Move the read outside the safe lock and explain the regression.
  3. Explain why putting the barrier inside a one-thread-at-a-time lock would block progress.
Worked solution

Read A=0, read B=0, then both write 1. A read outside the lock can be stale. If one worker holds the lock while waiting at a two-party barrier, the other cannot acquire the lock to reach it; the timeout exposes the deadlock pattern.

10

Exercises with worked solutions

Try before opening the solution. ★ applies an idea; ★★ combines ideas; ★★★ asks for design or proof.

Exercise 1 — Program versus process★

Can one program file have two running processes?

Worked solution

Yes; each invocation can have separate state and resources.

Exercise 2 — Page split★

Split address 4100 with 4096-byte pages.

Worked solution

Page 1, offset 4.

Exercise 3 — Scheduling★★

Jobs A=8 and B=1 arrive together. Compare FCFS A-first with B-first mean turnaround.

Worked solution

A-first completion 8,9 gives 8.5; B-first 1,9 gives 5. Ordering affects mean completion even with identical work.

Exercise 4 — Lost update★★

Two workers read 5 and each writes old+1. Final value?

Worked solution

6, not the intended 7.

Exercise 5 — Shared state★★

Which needs coordination: shared dictionary or thread-local loop index?

Worked solution

Shared mutable dictionary invariants need coordination; independent local indices do not by themselves create a shared-state race.

Exercise 6 — Deadlock order★★★

Two workers need locks X and Y. Give a consistent acquisition rule.

Worked solution

All workers acquire X before Y and release in reverse order. This removes the X→Y versus Y→X circular wait for these locks.

Exercise 7 — Critical boundary★★★

A last copy is borrowed by two callers. What must be atomic?

Worked solution

The availability check and decrement/loan creation must be one coordinated transaction. Locking only the decrement cannot prevent both callers passing the earlier check.

Exercise 8 — Lifetime★★

Why close a file even when parsing raises?

Worked solution

Release the resource predictably; a with block arranges cleanup on both normal and exceptional exit.

11

Self-check quiz

Choose an answer for feedback; reset to retry. A text answer key is available without JavaScript.

1

Threads in a process share?

2

Round robin chooses?

3

A page fault always means disk read?

4

A lock should cover?

5

GIL guarantees application transactions?

6

Consistent lock order helps prevent?

Answer key
  1. A — Stacks are separate.
  2. B — It rotates ready work.
  3. C — Faults can allocate or reject accesses too.
  4. A — Stale reads outside remain unsafe.
  5. B — Explicit coordination is still needed.
  6. C — It addresses a deadlock condition.
12

Guided reading

  • OSTEP processes — Read process states and distinguish ready from running.
  • OSTEP locks — Trace a lost update and its protected version.
13

Review and the next step

Explain exactly how the barrier causes a lost update, then state the locked invariant. Module 11 connects processes through network protocols.

14

Key terms

TermMeaning
Context switchSaving and restoring execution state to change running work.
Critical sectionOperations requiring coordinated access to shared state.
Virtual addressAn address interpreted through a process's mapping context.