Systems Programming: C, Processes & Concurrency
Core concepts, formulas and conditions at a glance.
See the learning route first
Follow the arrows. Choose a stage to open its first lesson. The full framework lists every topic.
- 01
C objects and data
Understand how values are stored and when pointers may access objects, then organize text, structures and dynamic data.
8 topics ↗ - 02
Build and execute programs
Follow source into running processes through preprocessing, linking, signals and child-process lifecycles.
5 topics ↗ - 03
Communicate and synchronize
Choose how data travels, then define who may change shared state and when participants wait or continue.
8 topics ↗ - 04
Scale and verify
Partition correct computations into parallel work, then check performance and correctness using equivalent workloads and reproducible evidence.
3 topics ↗
01 / Representation is a contract
Unsigned arithmetic wraps modulo its range; signed overflow is undefined. sizeof returns size_t in C bytes. Initialize automatic objects and match formatted-I/O conversions to actual argument types.
02 / Pointers need live bounds
Array arithmetic stays within the array or its one-past position; never dereference the latter. A multidimensional array decays to a pointer to a row, not a pointer to pointer.
03 / Text needs capacity and termination
Reserve strlen+1 bytes. Bounded reads can split a logical line. Check conversion results, suffixes and range; never treat arbitrary bytes as a terminated C string.
04 / Own every allocation
Check n≤SIZE_MAX/sizeof(*p) before multiplying. Check allocation results, initialize before reading, preserve the old pointer on realloc failure and end all borrowing before one eventual free.
05 / Build stages differ
Preprocessing expands tokens; compilation checks a translation unit; linking resolves external definitions. Headers describe interfaces. Macros can duplicate side effects, and include guards do not prevent cross-file multiple definitions.
06 / Signals need a minimal handler
Prefer sigaction and async-signal-safe operations. A small stop flag can defer cleanup to normal flow. Use an atomic mask-and-wait protocol when checking a predicate and sleeping for signals.
07 / Process lifecycle
fork duplicates execution with separate ordinary memory; exec replaces the image; waitpid collects status. Check each result, close unused inherited descriptors and decode wait status with its matching macros.
08 / Streams are not messages
Pipes and stream sockets can split or combine writes across reads. Define framing and loop over partial transfers. Pipe EOF requires drained data and every write endpoint closed.
09 / Shared storage needs a protocol
Shared memory removes some copying, not synchronization requirements. Use offsets across mappings. Semaphore permits track resources; mutexes protect invariants. Define initialization, shutdown and recovery ownership.
10 / Thread coordination
Keep arguments alive through use and join created threads correctly. Protect every conflicting access. A condition wait belongs in a predicate loop with its mutex; volatile is not general synchronization.
11 / Prevent circular waits
Acquire locks by stable global rank and include joins, condition waits and I/O in dependency analysis. A trylock loop can avoid blocking yet still livelock; timeouts alone do not diagnose deadlock.
12 / Measure equivalent work
Speedup=T₁/Tp using elapsed time for the same verified result. Partition output ownership, combine after dependencies complete and account for serial work, bandwidth, imbalance and synchronization costs.