---
title: 'Systems Programming: A Learning Path from Program Startup to I/O'
url: https://doc.liz6.com/en/systems-programming/00-learning-path
locale: en
area: systems-programming
tags:
- Systems programming
date: 2026-09-12
modified: 2026-09-12
description: For readers who can read and write C or Rust and understand pointers and processes. Prepare a Linux environment capable of compiling and debugging small programs; first, read the ABI examples for your machine's architecture, and use other architectures for comparison. This path does not require prior kernel compilation.
---

# Systems Programming: A Learning Path from Program Startup to I/O

For readers who can read and write C or Rust and understand pointers and processes. Prepare a Linux environment capable of compiling and debugging small programs; first, read the ABI examples for your machine's architecture, and use other architectures for comparison. This path does not require prior kernel compilation.

## What you will build

Connect source code, binaries, runtime behavior, system calls, and external effects. Explain buffering, errors, and persistence boundaries, and verify these using tools.

## Required reading and checkpoints

1. [ELF File Format](01-elf-and-binary-formats/01-elf-file-format.md) → [Loading and Startup: From ELF Entry to main](01-elf-and-binary-formats/03-loading-and-startup-start-main.md) → [Process Memory Layout](03-processes-and-memory/01-process-memory-layout.md).

   Compile a minimal program and inspect the ELF entry point and runtime memory map. Self-check: Distinguish between file offsets and virtual addresses; explain what work occurs before `main`; note the architecture and build options for every observation.

2. [Linux x86-64 System Call ABI](02-system-call-abi/01-x86-64-system-call-abi.md) → [Buffered I/O (stdio)](05-io-and-file-systems/01-buffered-i-o-stdio.md).

   Trace program output, moving from library buffering to `write`. On ARM64 machines, read the corresponding ARM64 section in the same directory. Self-check: Distinguish library buffering, `fflush`, `write`, and durable storage; be able to reproduce and handle a delayed I/O error.

3. [Pipes and socketpair](06-ipc-and-synchronization/02-pipes-and-socketpair.md) → [epoll and Event-Driven Programming](05-io-and-file-systems/03-epoll-and-event-driven-programming.md) → [Practical Valgrind and Sanitizers](08-performance-and-debugging/02-valgrind-and-sanitizers-in-practice.md).

   Add pipes or socketpairs to a program, then handle short reads/writes, EOF, blocking, and non-blocking modes. Self-check: Ready does not mean the complete message has arrived; error checking and resource closure must cover every exit path.

## Optional branches

Choose either [ARM64 ABI](02-system-call-abi/02-arm64-system-call-abi.md) or the main x86-64 section; subsequently, read [Dynamic Linking](01-elf-and-binary-formats/02-dynamic-linking-and-ld-so.md), [futex](06-ipc-and-synchronization/01-futex-the-kernel-hop-in-userspace-locks.md), and [io_uring](05-io-and-file-systems/02-io_uring.md) as needed. Performance analysis should be conducted only after establishing reproducible benchmarks and correct results.

## Completion task

Complete a small utility that reads input and passes it to a child process via a pipe. Test empty input, premature closure, and error paths. Include a system call trace, explaining where buffering occurs, where blocking happens, and which process owns each file descriptor. If you need to understand the implementation behind these interfaces, proceed to the [Kernel Path](../linux-kernel/00-learning-path.md).

It is acceptable to skip long proofs and implementation details during the first reading, but you must complete the self-checks for each phase. If you find yourself "knowing the terms but unable to explain the results," return to the current example, change one condition, and then proceed to the next section; there is no need to read the entire directory sequentially beforehand.
