Process States and Lifecycle in Linux: R, S, D, T, Z Explained

Process States and Lifecycle in Linux: R, S, D, T, Z Explained

What You'll Learn

  • What R / S / D / T / Z in the ps STAT column actually mean
  • The lifecycle of a process from fork to exit
  • A clear way to diagnose "the zombie won't go away" or "kill -9 won't kill it"

Quick Summary

  • A ps state is a single-letter code for the kernel's internal state
  • R=running/runnable, S=interruptible sleep, D=uninterruptible sleep, T=stopped, Z=zombie
  • A zombie is finished but not yet reaped by its parent — not a process, but unfinished cleanup

Assumptions (environment)

  • A typical Linux system (procps ps / top)
  • Check state codes in the STAT column of ps aux or via ps -eo stat

What Is a Process State?

Conclusion: A process state is the kernel's internal classification of how it's handling a process right now (run it on a CPU, make it wait, stop it, await reaping). ps projects that onto a single letter.

From birth to death, every Linux process is always in one state. The state is an internal attribute the kernel manages for scheduling — it distinguishes "is this eligible for the CPU", "is it waiting on something", and "is it already finished".

The state code shown by ps and top is that internal state mapped to one character. Start by observing the whole picture with ps.

$ ps -eo pid,stat,comm
  PID STAT COMMAND
    1 Ss   systemd
  812 S    sshd
 1043 R+   ps
 1044 S+   bash
 2210 Z    defunct

The first character of STAT is the main state; later characters are auxiliary flags (covered below). The row whose COMMAND is defunct is a zombie.

R / S / D - What's the Difference Between Running and Sleeping?

Conclusion: R is on a CPU (or waiting its turn), S is an interruptible wait, D is an uninterruptible wait. A growing number of D processes points to stuck I/O.

The states you see most often are R for execution and S / D for waiting.

  • R (Running / Runnable): Executing on a CPU, or sitting on the run queue waiting for a turn. A process that "can run".
  • S (Interruptible Sleep): Waiting for some event (input, a timer, a socket receive). It can be interrupted by a signal. Most processes on a desktop or server sit in S most of the time.
  • D (Uninterruptible Sleep): Mainly waiting on low-level completion such as disk I/O. It cannot be interrupted, even by a signal. Normally it passes in an instant, but a growing number of processes stuck in D is a warning sign (storage failure, an unresponsive NFS mount, etc.).
# Extract only processes in the D state (waiting on I/O)
$ ps -eo pid,stat,comm | awk '$2 ~ /D/'

A process in D does not accept signals, so even kill -9 won't kill it right away. Most "I ran kill -9 but it won't go away" processes are either this D (I/O wait) or a zombie (Z). You have to wait for the underlying I/O to finish.

T / t - What Is a Stopped Process?

Conclusion: T is a process suspended by SIGSTOP / Ctrl+Z, t is one stopped under a debugger's trace. Both use no CPU and wait to be resumed.

  • T (Stopped): Suspended via job control. Entered by Ctrl+Z (SIGTSTP) or kill -STOP. Resume with fg / bg or SIGCONT.
  • t (Tracing stop): Stopped under a debugger such as gdb or strace.
$ sleep 300 &
$ kill -STOP %1     # suspend → STAT becomes T
$ ps -o pid,stat,comm -p $(pgrep -n sleep)
  PID STAT COMMAND
 3120 T    sleep
$ kill -CONT %1     # resume → back to S

T does not mean "dead" — it means "suspended, waiting to resume". To terminate it, send SIGCONT to resume first, then SIGTERM (a stopped process may not process TERM while suspended).

What Is a Zombie (Z), and Why Won't It Die?

Conclusion: A zombie (Z / defunct) has finished but its parent hasn't yet collected (reaped) its exit status. The body is gone; all that remains is one entry in the process table.

When a process calls exit(), it doesn't vanish immediately. The kernel keeps its exit status (exit code) and waits for the parent to come collect it. This wait-to-be-reaped state is a zombie, shown as Z in ps and <defunct> in the COMMAND column.

The key properties of a zombie:

  • Its memory, files, and CPU are already released. All that remains is one process-table entry (its PID and exit status).
  • Because it is "already dead", you cannot kill it (there's no live process to receive a signal).
  • It disappears the instant the parent calls wait() / waitpid() (reaping it).
# Extract only zombies
$ ps aux | awk '$8 ~ /Z/ { print $2, $11 }'

A few zombies are harmless, but a pile of them indicates a bug in the parent (failing to wait on its children). PIDs are a finite resource, so zombies that exhaust the PID space can prevent new processes from being created.

Orphan vs Zombie - What's the Difference?

Conclusion: An orphan is a living process whose parent died first; it's adopted by PID 1 (init / systemd). A zombie is a dead process. Orphans are normal; lingering zombies are not.

Orphan processes are easily confused with zombies, yet they are nearly opposites.

Aspect Orphan Zombie (Z)
Alive? Alive Dead (already exited)
Cause Parent exited first Parent isn't calling wait
Adopted by PID 1 (init/systemd) Reaped by parent (or PID 1)
A problem? Usually harmless A parent bug if there's many

When a parent exits before its child, the child becomes an orphan and is automatically reparented to PID 1 (init or systemd). PID 1 calls wait periodically, so when that orphan later exits it is reaped right away and never lingers as a zombie. This is part of how a nohup'd or daemonized process keeps running after you close the terminal.

# A parent PID of 1 means an orphan (adopted by PID 1)
$ ps -eo pid,ppid,stat,comm | awk '$2 == 1'

From fork to exit - The Process Lifecycle

Conclusion: A process is duplicated by fork, replaces its image with exec, cycles through running (R/S/D) and stopped (T), exits, and is fully removed when the parent reaps it. A zombie is this last step left unfinished.

Stringing the states together as a lifecycle, the life of a process looks like this.

  1. fork(): The parent creates a child as a copy of itself. Right after, the child is nearly identical to the parent.
  2. exec(): The child overwrites its memory image with another program (fork + exec is the basic pattern for launching a new command).
  3. Running and waiting: Under the scheduler, it moves between R (running) ⇄ S / D (waiting) ⇄ T (stopped) while doing its work.
  4. exit(): The program terminates. Leaving its exit status behind, it becomes a zombie (Z) and awaits collection by the parent.
  5. wait() / waitpid(): The parent collects the child's exit status (reap). At that instant the zombie disappears and the PID is freed.

This model explains common symptoms along a single line.

  • A lingering zombie → step 5 is missing (the parent isn't calling wait)
  • An orphan → the parent exited before step 4 → PID 1 takes over
  • kill -9 won't kill it → either D in step 3 (I/O wait), or it's already a zombie from step 4
# Roughly tally process counts by state
$ ps -eo stat --no-headers | cut -c1 | sort | uniq -c | sort -rn
    142 S
     12 I
      4 R
      1 Z

How to Read the STAT Auxiliary Flags

Conclusion: Characters after the first in STAT are auxiliary. + is a foreground job, s a session leader, l multi-threaded, < / N priority. Read them together with the main state letter.

STAT values like Ss or R+ are two or more characters because auxiliary flags follow the main state. The main ones:

Flag Meaning
s Session leader
l Multi-threaded
+ In the foreground process group
< High priority (negative nice value)
N Low priority (positive nice value)
L Has pages locked into memory

For example, systemd's Ss reads as "interruptible sleep (S) and session leader (s)", while ps's own R+ reads as "running (R) and a foreground job (+)".

When you want to tally by the main letter only, strip the first character with ps -eo stat | cut -c1 to ignore the auxiliary flags (the tally example above uses this trick).

Summary: State Code Cheat Sheet

Conclusion: R can run, S/D are waiting (D uninterruptible), T is stopped, Z is a zombie. The practical trap is that zombies and D processes can't be cleared with kill.

Code State Meaning Killable?
R Running / Runnable On a CPU or run queue Yes
S Interruptible sleep Waiting on an event (normal) Yes
D Uninterruptible sleep Waiting on I/O No (I/O wait)
T Stopped Ctrl+Z / SIGSTOP After CONT resumes it
Z Zombie Exited, awaiting reap No (handle parent)

Once you can read states, vague symptoms like "it's heavy", "it won't finish", or "it won't die" translate into the concrete question of what the kernel is making that process do. Learn this alongside how to send signals, and process troubleshooting gets noticeably faster.

Next Reading