Skip to content
ALB Wiki

Processes

This is an old revision of this page — revision 1 (2026-10-25 14:49:19 UTC). It may differ from the current revision.

A process is a running program — a pid, an address space, open file descriptors, a parent, a state. Every process on Linux descends from PID 1 (init/systemd) through fork() — the whole system is one family tree. This chapter teaches you to see it: ps, top, signals, job control, and the /proc filesystem where the kernel exposes every process's innards as readable files.

The lifecycle — fork, exec, wait, exit

pid = fork();        // clone — parent and child both continue
if (pid == 0)        // child branch
    execvp("prog", args);   // replace this process's image
else
    wait(&status);   // parent collects the child's exit code

fork() duplicates; exec() replaces the copy with the new program; wait() reaps. Every process is born a clone of its parent, then re-skinned as its real program. The exit code (0–255) the child leaves is the contract the parent collects — $? in the shell.

When a child dies before its parent waits, it becomes a zombie — Z in ps, dead but unreaped, holding only its exit status. An orphan whose parent dies is re-parented to PID 1.

Seeing them — ps and friends

ps aux                  # the classic full listing
# USER  PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ps -ef                  # SysV style — shows PPID
ps -ejH                 # the family tree
ps --forest -e          # visual tree
pgrep -l sshd           # pids by name
pidof bash              # single name → pids
top                     # the live view — sort by M(em), P(cpu), T(ime)
htop                    # the better live view
pstree -p               # the tree with pids

STAT codes — R running, S sleeping, D uninterruptible (usually I/O), T stopped, Z zombie, s session leader, + foreground, l multithreaded. D-state processes can't be killed — they're mid-syscall in the kernel.

Signals — the messaging system

kill PID            # SIGTERM (15) — please exit politely
kill -9 PID         # SIGKILL — the kernel kills it NOW (no cleanup)
kill -HUP PID       # SIGHUP — hangup → reload config for daemons
kill -INT PID       # SIGINT (2) — Ctrl-C
kill -TSTP PID      # SIGTSTP — Ctrl-Z
kill -CONT PID      # resume a stopped one
kill -USR1 PID      # user-defined — daemons use as triggers
kill -l             # all 31 signals
killall name        # by name
pkill -f pattern    # by cmdline pattern

The two uncatchables: SIGKILL and SIGSTOP — the kernel's guarantees that nothing can refuse death or suspension. Everything else a process may trap/handle/ignore.

Job control — the shell's own processes

cmd &               # background
jobs                # the job table — %1 %2 ...
fg %1               # bring to foreground
bg %1               # resume suspended in background
Ctrl-Z; bg          # the suspend-and-background combo
disown %1           # remove from job table — survives shell exit
nohup cmd &         # immune to SIGHUP — survives logout

Ctrl-C = SIGINT to the foreground group; Ctrl-Z = SIGTSTP; Ctrl-\ = SIGQUIT (with core dump). jobs -l shows pids.

Sessions and process groups

A session groups process groups under a controlling terminal — setsid starts a new one (how daemons detach from terminals). The login shell leads a session; pkill -u alice kills all her processes. Daemonization = fork, setsid, detach tty, chdir /, close fds, redirect stdio to /dev/null — the classic dance systemd now does for services.

/proc — the process's innards

ls /proc/$$         # YOUR shell's process, as files
cat /proc/$$/status     # state, memory, uids
cat /proc/$$/cmdline | tr '\0' ' '   # its argv
ls -l /proc/$$/fd       # its open files — the fds!
cat /proc/$$/environ | tr '\0' '\n'  # its environment
cat /proc/loadavg       # 1/5/15-min load + running/total
cat /proc/meminfo       # the memory ledger
cat /proc/cpuinfo       # the CPUs

/proc/PID/fd/ alone is worth the chapter — every open file, socket, and pipe as a symlink. lsof and ls -l /proc/*/fd show who holds what.

Priorities — nice and the scheduler

nice -n 10 cmd          # run it nicer (lower priority, -20..19)
renice +5 -p PID        # change a running one
ps -o pid,ni,comm       # see nice values

Higher nice = lower priority — "nicer" to others. chrt, ionice, taskset reach the deeper schedulers (RT classes, I/O priority, CPU pinning).

Resource limits

ulimit -a               # this shell's limits — fds, core size, procs, memory
ulimit -n 4096          # raise fd ceiling
cat /proc/PID/limits    # a running process's limits
timeout 30 cmd          # kill after 30s — the blunt instrument
systemd's LimitNPROC/LimitNOFILE — the service-level equivalents

ulimit -n (max open files) is the one you'll actually hit — busy servers bump it constantly.

Monitoring beyond top

vmstat 1              # memory + IO + CPU, per second
iostat -x 1           # disk I/O
mpstat -P ALL 1       # per-CPU
dstat                 # the everything-monitor
free -h               # memory now
watch -n1 'ps aux --sort=-%cpu | head'   # your own live monitor

Load average (uptime) = runnable processes averaged over 1/5/15 min — 4.00 on 4 CPUs = saturated; on 8 CPUs = half-loaded. Interpret relative to core count.

Where process work goes wrong

SymptomCause
kill didn't kill itProcess ignored SIGTERM — escalate to -9
kill -9 didn't kill itD state — mid-syscall, often dead NFS/disk I/O
Zombie piling upParent not wait()ing — a parent bug; kill the parent
Daemon dies at logoutNeeded nohup/setsid/disown — SIGHUP
Ctrl-C doesn't workProcess traps or ignores SIGINT
Can't find the processps -ef | grep name; pgrep -f for cmdline
"Too many open files"ulimit -n — the fd ceiling

Exercises

  1. sleep 300 & — job control: jobs, fg, Ctrl-Z, bg, kill.
  2. ls -l /proc/$$/fd — inspect your shell's own open files.
  3. bash -c 'sleep 99' then ps -ejH — find the fork relationship.
  4. kill -TSTP a process then -CONT — freeze and thaw it.
  5. watch -n1 cat /proc/loadavg — watch load breathe.
  6. ulimit -n — your fd ceiling; then raise it and note where it matters.

Timeline

ConceptMechanism
Birthfork() → exec()
Deathexit() → zombie → wait()
PID 1The ancestor of all — systemd/SysVinit
SignalsInter-process interrupts
/procThe kernel's process window

See also

Categories: Handbook · Linux · Linux Handbook
This page was last edited 2026-10-25 14:49:19 UTC by ALB Team. What links here