Week 7 — Processes, Syscalls, Signals, a Mini-Shell, and System Startup

Course 4 syllabus

Overview

This week crosses from the machine into the operating system: how Linux runs programs, and how the system itself comes up. It consolidates the processes/syscalls week with the boot/systemd week because they bracket the same story — the kernel boots, user space starts, and then processes are created, scheduled, and torn down. You will learn the process lifecycle (fork/exec/wait), system calls as the user↔︎kernel boundary, signals, and /proc, then build a mini-shell that ties them together. You will also trace how a system gets from firmware through the kernel to systemd-managed services and journald logs.

This is where the assembly/ABI knowledge (Weeks 4–5) meets the kernel: a syscall is a controlled trap into the kernel with its own register convention. The mini-shell and /proc inspection are direct precursors to the capstone’s syslens.

Readings

  • HLW Ch. 8: processes and resource utilization. Extract: the process lifecycle, scheduling, and resource limits.
  • HLW Ch. 2: process commands. Extract: ps, /proc, signals from the shell.
  • HLW Ch. 5–7: how the kernel boots, how user space starts, and system configuration/logging/journald. Extract: the firmware→kernel→init→services chain.

Key Concepts

The process lifecycle

A process is a running program with its own address space (Week 8), file descriptors, and registers. fork clones the calling process (copy-on-write address space); exec replaces the image with a new program; wait reaps a child’s exit status. This fork/exec/wait pattern is how every program on the system is launched, and building a shell makes it concrete.

System calls — the user/kernel boundary

A syscall is the controlled entry into the kernel: load the syscall number and arguments into registers (an ABI like Week 5’s, but for the kernel — on AArch64, x8 holds the number, args go in x0x5, and svc #0 traps), and the kernel executes in privileged mode and returns in x0. strace reveals the syscalls a program makes — often the clearest way to understand what software actually does. Syscalls are the only way user code touches files, memory mappings, processes, and devices.

The x86-64 equivalent is the same idea with a different register convention: the syscall number goes in rax, arguments in rdi, rsi, rdx, r10, r8, r9 (note r10, not rcx — the syscall instruction clobbers rcx), and the dedicated syscall instruction traps, returning in rax. Two things differ from ARM64 worth noting: the kernel syscall ABI is not the same as the function-call ABI on either platform (e.g. x86-64 user calls pass the 4th arg in rcx, but syscalls use r10), and syscall numbers differ between ISAswrite is not the same number on ARM64 and x86-64 — which is why a statically-encoded syscall is non-portable and why strace output is ISA-specific.

Signals and /proc

Signals are asynchronous notifications (SIGINT, SIGTERM, SIGCHLD, SIGSEGV); a process installs handlers or takes the default. A shell uses them for job control. /proc is a virtual filesystem exposing kernel state as files — /proc/[pid]/status, maps, fd, stat — readable with ordinary I/O, the basis of every process-inspection tool (and the capstone).

System startup

Power-on → firmware → bootloader → kernel (decompress, init hardware, mount root) → the first user process (PID 1, systemd) → service units brought up per dependency order → journald collecting logs. Understanding units, dependencies, and journalctl is essential for operating any Linux system (and the Jetson in Course 1).

Theory Exercises

  1. Explain fork/exec/wait and draw the process tree for a shell running a pipeline.
  2. Describe the AArch64 syscall mechanism (number in x8, args x0x5, svc, return in x0) and the x86-64 one (number in rax, args rdi/rsi/rdx/r10/r8/r9, syscall); explain why the syscall ABI differs from the function-call ABI (Week 5) on each, and why syscall numbers are not portable across ISAs.
  3. Explain how copy-on-write makes fork cheap and what happens on the first write after fork.
  4. List the fields of /proc/[pid]/stat you’d need to compute a process’s CPU usage; explain /proc/[pid]/maps.
  5. Trace the boot chain from firmware to a running service; explain how systemd orders units by dependency.

Implementation

Build a mini-shell (labs/week07-processes-boot): parse a command line, fork/exec, wait, support pipes (|) and redirection (>/<) via dup2, and handle SIGINT/job control. Read process info from /proc. Separately, write a small program that prints another process’s status by parsing /proc/[pid]/. Inspect a service’s status and logs with systemctl/journalctl.

Measurement / Inspection

strace your mini-shell and a real program; compare the syscalls. Verify pipes/redirection work like the system shell. Parse /proc/[pid]/stat to report a process’s state and CPU time and cross-check with ps. Walk a unit’s dependency tree (systemctl list-dependencies) and read its journalctl logs.

Expected baselines: the mini-shell runs pipelines and redirections correctly and handles Ctrl-C via signals; strace shows the expected fork/execve/dup2/wait pattern; /proc parsing matches ps. The boot/service trace shows a coherent dependency-ordered startup.

Connections

The /proc parsing and process model are the core of the Week 10 syslens capstone. The syscall boundary builds on Week 5’s ABI; the address space referenced here is detailed in Week 8. Process/systemd knowledge is used directly to deploy and operate the Jetson runtime in Course 1.

Further Reading

  • HLW Ch. 2, 5–8; CS:APP (Bryant & O’Hallaron) Ch. 8 — exceptional control flow and the x86-64 syscall path.
  • The Linux Programming Interface (Kerrisk) — processes, signals, and syscalls (reference).
  • man 2 fork, man 2 execve, man 5 proc, man 1 systemctl.