Free — no signup required

Stage 5: PID 1 and systemd

3 min read

The Ancestor of All Processes

Once switch_root completes, the kernel executes /sbin/init on the real root filesystem. This process receives Process ID 1 (PID 1) — the first and most privileged user-space process. Every other process on the system is a descendant of PID 1.

On virtually all modern Linux distributions, /sbin/init is a symbolic link to systemd — confirmable either by checking what /sbin/init points to, or simply asking which command name owns PID 1 directly.

What systemd Does

systemd's job is to bring the system from a bare kernel to a fully operational state. It does this by starting units — systemd's abstraction for anything it manages (services, mount points, devices, timers, sockets). Units are defined in plain-text files with a .service, .mount, .target, etc. extension.

systemd uses targets (analogous to the old SysV "runlevels") to define system states:

Target Equivalent Runlevel Description
rescue.target 1 Single-user, minimal services, root shell
multi-user.target 3 Full multi-user, no GUI
graphical.target 5 Full multi-user with GUI
reboot.target 6 System reboot

systemd starts units in parallel where possible (unlike the old sequential SysV init scripts), dramatically reducing boot time. It tracks dependencies between units — if network.service must start before sshd.service, systemd knows this from the After= and Requires= directives in the unit files. systemd-analyze blame ranks every unit by how long it took to start, immediately surfacing which service is dragging out boot time (commonly things like unattended-upgrade services, snap mounts, or network-wait units), while systemd-analyze critical-chain shows the actual dependency chain responsible for total boot time — the sequence of units where each had to wait on the one before it.

Why PID 1 Is Special

PID 1 has a unique responsibility beyond starting services: it is the reaper of orphaned processes. When any process's parent dies before the child, the child becomes an "orphan." The kernel automatically re-parents all orphans to PID 1. PID 1 must then call wait() to collect their exit status and prevent them from becoming zombie processes (processes that have exited but whose exit status hasn't been collected, consuming a process table entry).

If PID 1 itself crashes or is killed, the kernel has no recovery path — it triggers a kernel panic and halts the system. This is why running arbitrary workloads as PID 1 inside containers is dangerous: if your application crashes, the container dies with no chance of recovery. Proper container init systems (like tini) exist specifically to handle this correctly.

Interview Tip

A frequent container/Kubernetes interview question: "Why shouldn't you run your application as PID 1 in a container?" The answer has two parts: (1) Signal handling — PID 1 receives SIGTERM when a container stops, but most applications don't handle SIGTERM correctly when running as PID 1 because the kernel does not apply default signal handlers to PID 1. Your app may ignore SIGTERM and get SIGKILL'd after the grace period, causing unclean shutdown. (2) Zombie reaping — if your app spawns child processes (e.g., shell scripts), those children become zombies when they exit if PID 1 doesn't call wait(). Use a minimal init like tini (or Docker's --init flag) to handle both correctly.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free