Process Lifecycle
How a Linux process comes into existence, runs, and terminates - the fork/exec model, parent-child relationships, and what happens to a process after it exits.
Every process on a Linux system except the very first one (PID 1) was
created by another process. That parent-child chain, and the two system
calls behind it, explain most of what you see in ps output.
fork and exec
Creating a new process is actually two separate steps:
fork()- the calling process is duplicated. The new process (the child) is an almost-exact copy of the parent, with its own PID, running the same code from the same point.exec()- the child replaces its own memory image with a different program entirely. This is how runninglsfrom Bash works: Bash forks itself, and the child immediately execs intols.
Most of the time you don't call these directly - a shell does it for every command you run - but the model explains why a forked child inherits things like open file descriptors and environment variables (see Environment Variables) from its parent: it briefly was a copy of the parent before exec replaced its code.
PID, PPID, and the process tree
Every process has a PID (process ID) and a PPID (parent process ID) recording who created it. PID 1 is the init system (see systemd and Services), and every other process traces back to it through a chain of parents.
pstree -p
systemd(1)─┬─sshd(892)───sshd(1203)───bash(1204)───pstree(1522)
├─cron(701)
└─nginx(1050)─┬─nginx(1051)
└─nginx(1052)
ps -ef | head -5
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:14 ? 00:00:02 /sbin/init
root 701 1 0 09:14 ? 00:00:00 /usr/sbin/cron
root 892 1 0 09:14 ? 00:00:00 sshd: /usr/sbin/sshd
root 1050 1 0 09:14 ? 00:00:00 nginx: master process
Process states
ps and top show a state code for every process:
| Code | State | Meaning |
|---|---|---|
R |
Running | Actively executing or ready to run |
S |
Sleeping | Waiting for an event (the common resting state) |
D |
Uninterruptible sleep | Waiting on I/O, usually disk - can't even be killed until it returns |
T |
Stopped | Suspended, typically by a job-control signal - see Job Control |
Z |
Zombie | Has exited, but its parent hasn't yet collected its exit status |
Termination and exit status
When a process finishes, it doesn't disappear immediately - it becomes a
zombie, retaining just enough information (its exit status) for its
parent to retrieve with a wait() call. A well-behaved parent does this
promptly; a large number of long-lived zombie processes usually points to
a parent process that's buggy or never calling wait().
If a parent exits before its child does, the child is orphaned and gets re-parented to PID 1 (or, on systemd systems, sometimes a designated subreaper), which will reap it once it exits.
The exit status itself is a number 0–255, retrievable from the shell as
$? immediately after a command runs - 0 conventionally means success,
anything else signals failure, and a specific non-zero value is often used
to indicate which failure occurred. See
Shell Scripting for using this in practice, and
Signals for the other way a process's lifecycle can
end - being killed by a signal rather than exiting on its own.