This book guides a computer science graduate from basic Unix and C through Linux kernel internals, userspace services, desktops, applications and Wine toward independent systems investigation. It is a long apprenticeship, not a certification or a guarantee of expertise. The similarly named Linux From Scratch project teaches readers to build a Linux distribution; this is a separate Linux kernel curriculum, not its official guide. No finite book covers every driver, architecture, application, configuration, or release.
Baseline and evidence#
The kernel historical teaching baseline is upstream Linux v6.12, with versioned documentation. It is not a recommendation to deploy an unpatched kernel. A distribution may backport fixes and behavior without changing the apparent upstream version; a current kernel may have moved or replaced the code. Userspace and Wine projects have separate independently pinned source versions; they are not a jointly tested compatibility matrix. Pin tools separately when an exercise needs a particular version. When comparing another version, use Git to inspect the change and read its surrounding configuration rather than assuming names and paths are unchanged.
An annotated source path establishes what that version can do under stated conditions. It does not establish which path your machine executed. A runtime trace describes one observed execution, with its instrumentation, workload and losses; it does not establish all possible executions. Separate direct evidence, inference, synthetic examples and unanswered questions in your notes. The chapter diagrams are teaching models, not captured executions unless explicitly stated. The figure below sorts the evidence kinds used in this curriculum and what each can and cannot show.
- Source at a tag
- What the v6.12 code implements under stated conditions; it does not show which path your machine ran.
- Configuration
- Your .config, architecture, compiler and patches decide which paths exist on a given system.
- Runtime observation
- One captured output from one host; it does not establish all possible executions.
- Synthetic example
- A labeled teaching program or invented input; useful for practice, not a measurement.
- Open question
- What remains unverified, with the next check that would settle it.
What makes a Linux system#
Linux is the kernel: it manages processes, memory, devices and interfaces used by programs. A shell, compiler, C library and utilities are userspace programs; many systems use GNU components, but neither GNU nor any particular shell is the kernel. The C library often supplies the convenient function that prepares a system call and translates a negative kernel error into userspace errno. A distribution selects a kernel, configuration, patches, libraries, package manager, services and update policy. Firmware and a bootloader prepare a machine and hand control to the kernel according to an architecture-specific contract; they are not interchangeable with PID 1, the first userspace process.
This boundary matters when debugging. A shell's command not found, a dynamic loader's missing-library error, a rejected system call, and a device driver's error may look like one failed command, yet require different evidence. Identify the layer and version before attributing a failure to Linux itself.
A multi-year study plan#
These are planning ranges for roughly 5–10 focused hours per week, not promises. The original kernel phases total approximately 25–50 months and 1,090–2,150 hours; the userspace and Wine phases add roughly 24–48 months and 1,040–2,050 hours; overlap, prior systems work, interruptions and hardware availability change elapsed time. Some investigations take far longer. A source-only learner can complete reading gates while recording runtime work as pending.
| Phase | Parts and entry | Approximate effort | Evidence to retain |
|---|---|---|---|
| Foundations | 1–2: system map, build and boot | 3–6 months, 120–250 hours | Shell and C notes, source navigation, a build record or documented blocker |
| Execution and memory | 3–4: scheduling, memory ordering | 4–8 months, 180–350 hours | Scheduling timeline, synchronization and fault explanations |
| Files and I/O | 5–6: allocation, block I/O | 4–8 months, 180–350 hours | VFS and storage maps, crash-consistency hypothesis |
| Networks and devices | 7–8: sockets, driver model | 4–8 months, 180–350 hours | Packet path and device ownership diagrams |
| Specialization and isolation | 9–10: graphics, credentials | 4–8 months, 180–350 hours | One subsystem study and a bounded security model |
| Investigation and practice | 11–12: virtual I/O, systems engineering | 6–12 months, 250–500 hours | Measurement record, review exercise and capstones |
| Userspace and services | 13–15: userspace map, systemd, identity and networking | 6–12 months, 260–500 hours | Source-pinned service and authorization paths |
| Desktop and media | 16–18: graphics, toolkits, audio | 8–16 months, 340–650 hours | Buffer, event-loop and audio graph ownership maps |
| Applications and Wine | 19–21: applications, Wine architecture, Wine graphics | 10–20 months, 440–900 hours | Userspace capstone, compatibility evidence and Wine capstone |
Read the first four parts in order. Later, specialize and revisit foundations when a dependency is unclear. The kernel research atlas and userspace project atlas are starting maps for choosing a next question, not a complete list of Linux expertise.
Prerequisite matrix#
| Starting point | First target | Return when needed |
|---|---|---|
| New to shell or C pointers | Part 1 | Shell, C objects, lifetime and ABI |
| Comfortable with C and Unix | Review Parts 1–2 | Architecture, configuration and boot contracts |
| Familiar with kernel development | Part 3 onward | Baseline, execution context and version differences |
| Investigating a particular subsystem | Its part after core execution | Memory, locking, ownership and lifetime |
Weekly study routine#
A practical five-session cycle is read, trace, experiment, explain, review. First read the chapter and source with unfamiliar terms recorded. Next choose a single operation and follow a normal path and a meaningful error branch; record the configuration and how any indirect call is selected. Then run a bounded exercise appropriate to your route, or analyze the supplied source-only example. Write down expected results before looking at observations. Explain the path in your own words and draw the objects and their owners. Finally answer the knowledge check without the text, compare your explanation to the cited source, and revise the notebook with unresolved questions. An hour of careful tracing can be more useful than a day of collecting names.
Gates at part boundaries#
Each gate asks for an artifact and an explanation to another person or to your future self. Use the chapter checkpoints for detailed criteria. If you cannot explain a dependency, return to its prerequisite, work a smaller example and retry; do not mark a failed runtime experiment as a pass merely because source reading was possible.
| Part | Artifact and readiness gate |
|---|---|
| 1 | Explain a process, file descriptor and pointer lifetime; retain a safe shell transcript and source map. |
| 2 | Draw build-to-PID-1 and syscall-to-exec paths, with configuration and one failure branch. |
| 3 | Explain a wakeup, scheduling decision and deferred-work context using a timeline and lock assumptions. |
| 4 | Explain a publication/lifetime argument and a fault-to-page-table path with a counterexample. |
| 5 | Trace pathname, VFS objects and a filesystem operation, including references and an error. |
| 6 | Trace a storage request and distinguish completion from persistence; compare two IPC lifetimes. |
| 7 | Map a packet from socket through device or policy and name namespace and configuration boundaries. |
| 8 | Explain device discovery, resource ownership and safe teardown for a selected bus and driver. |
| 9 | Produce a focused subsystem map with its userspace interface and portability limitations. |
| 10 | Analyze authority, isolation and one virtualization boundary with an explicit threat model. |
| 11 | Produce a measurement and testing plan identifying instrumentation effects and untested paths. |
| 12 | Present a reproducible investigation or reviewable patch analysis, including alternatives and remaining uncertainty. |
| 13 | Trace a libc, loader or bus request across process boundaries and one error. |
| 14 | Explain a unit, job and service readiness timeline with a cleanup case. |
| 15 | Separate authentication, authorization, network and storage service authority. |
| 16 | Explain a display buffer's commit, ownership and release with a protocol boundary. |
| 17 | Trace an application event through toolkit, session and portal state. |
| 18 | Explain a media graph's buffer and policy lifecycle with an interruption. |
| 19 | Present a bounded cross-project investigation and competing explanations. |
| 20 | Trace a Wine object or handle through an ABI and lifetime boundary. |
| 21 | Present a compatibility hypothesis with a controlled test plan and explicit untested cases. |
These are evidence gates, not examinations administered by kernel maintainers. Source-only completion demonstrates source analysis under the stated assumptions; it does not demonstrate a boot, a measured result, operational competence, or expert qualification.
Choose a lab route#
Source-only requires a browser or a checkout of the tagged source and time to draw and explain paths. Supplied worked cases provide evidence even without a compiler or VM. Own-host read-only exercises use ordinary permissions, your own short-lived processes and observations such as /proc; results describe your host kernel, not automatically v6.12. Avoid exposing other users' process details in shared notes.
Disposable guest work uses an x86-64 QEMU guest, a separate kernel, initramfs or disk image, and an ordinary unprivileged host account. Label host and guest terminals, prompt, working directory and image paths before every command. Never give a physical disk, host mount, host firewall, host sysctl or host kernel module to a destructive exercise. Keep a clean image copy and retain logs; stop the VM and discard only lab copies to recover. Filesystem mutation, networking changes, crashes, fuzzing, hotplug and module insertion belong in a disposable guest or disposable image. A guest is not a substitute for backups or a security boundary against a hostile workload.
Chapter 08 specifies packages, resources and a reproducible intended build and boot. Its v6.12 kernel has not been successfully booted in the recorded author environment. Attempts using GCC 16 failed on C23-related build errors with both EFI and non-EFI configurations; the documented Ubuntu 24.04/GCC 13 alternative remains unverified here. Preserve the exact error, config and tool versions if your attempt fails; do not assume the VM will start immediately. No PID 1 or guest /proc output is claimed as observed by the authors.
Wine route: use only self-authored test programs in a new private prefix when the relevant tools are available; a Wine prefix is not a security sandbox. The authors did not run Wine, Windows conformance or the PE labs. Record a source-only result when those tools are unavailable.
Hardware and architecture contrast may require a suitable board, serial access, recovery media and device-specific documentation. arm64 source can be studied without hardware; an arm64 guest needs its own build, machine and firmware choices. Check access and recovery before trying hardware. Build time, disk space and RAM depend on configuration and parallelism; chapter 08 gives concrete starting budgets. A C toolchain, Git and optionally QEMU, BusyBox and readelf support different exercises; none is required for the source-only route.
Reading the code and keeping a notebook#
Start at a named interface and locate its definition, callers and relevant data structure. For each call, check the active Kconfig option, architecture, compile-time alternatives and runtime state. Follow function-pointer initialization to a specific operations table before claiming a target; macros, inline functions, generated files and static calls make a text search incomplete. Read both the callee and its callers, then trace resource acquisition and unwind in reverse order. Compare tags with Git history when a symbol is absent. A search returning no matches is a question about scope and spelling, not proof that a behavior cannot happen.
Use this notebook template for every investigation:
Question and expected observation:
Source tag/commit, files and symbols:
Architecture, CONFIG options, compiler, boot arguments and tool versions:
Caller, execution context and indirect-call selection:
Objects, owners, references, locks and lifetime:
Normal path and conditional branches:
Error, cancellation or teardown path:
Evidence: source / synthetic model / actual command and captured output:
Interpretation, limits, competing explanation and next check:
For example, ask why an invalid descriptor fails on a read. At v6.12 inspect ksys_read in fs/read_write.c, record how a descriptor is looked up and what happens if lookup fails, and distinguish the caller's descriptor number from the referenced open-file object. State whether you only inspected source or ran a userspace program, and capture that program's host kernel and return value. A trace of one failed call cannot establish the behavior of all filesystems or all versions. As you learn locking and references, add their exact lifetime and context rather than retroactively calling an early sketch complete.
How to read and measure progress#
Each chapter has prerequisites, goals, a source walkthrough, practice, questions, answers, a checkpoint and sources. Use search and the glossary to return to a term; the outline follows chapter headings. Theme, reading size, focus mode and completion marks are stored locally in your browser. A completion mark is a bookmark, not proof of competence. Printing produces a paper-friendly chapter view. For further work consult the kernel development process guide and the relevant subsystem maintainers' documentation, then verify against the version you actually use.