Process Lifecycle in Linux
A process is created by fork (or clone()), often runs a new program via exec, and eventually exits. The kernel sends SIGCHLD to the parent when a child terminates; the parent should wait() (or waitpid()) to reap the child. If the parent does not reap, the child remains a zombie until the parent does so or the parent exits (then init adopts and reaps). You cannot kill a zombie — it is already dead; only the parent (or init) can clear it by waiting. See Signals for SIGCHLD and signal handling.
Creation, execution, and termination
Section titled “Creation, execution, and termination”- fork() — Creates a child process as a copy of the parent (copy-on-write for memory). Returns twice: PID of child in parent, 0 in child. The child gets a new PID.
- exec() — Replaces the current process’s program (code, data, heap, stack) with a new executable. File descriptors (unless marked close-on-exec), PID, and parent do not change. Often used in the child after fork (fork + exec is how shells run commands).
- exit() — Process terminates; kernel keeps a small record (PID, exit status) until the parent calls wait() or waitpid(). Until then the process is in the zombie state.
Zombie processes
Section titled “Zombie processes”A zombie (state Z or <defunct> in ps) is a process that has exited but has not been reaped by its parent. The kernel keeps the PID and exit status so the parent can retrieve them with wait().
You cannot kill a zombie
Section titled “You cannot kill a zombie”The process is already dead — it has no code running. SIGKILL and SIGTERM have no effect. The only way to remove a zombie is for the parent to call wait() or waitpid(). If the parent is stuck or does not implement waiting:
- Restart or kill the parent — When the parent exits, the kernel reparents the zombie to init (PID 1); init reaps all children, so the zombie disappears.
- SIGCHLD handler — If you control the parent, install a handler for SIGCHLD that calls
waitpid(-1, &status, WNOHANG)to reap children as they exit and avoid zombies.
Orphan processes
Section titled “Orphan processes”If the parent exits before the child, the child becomes an orphan. The kernel reparents it to init (PID 1). Init will reap it when it exits, so orphans do not become permanent zombies.
Relevant tools
Section titled “Relevant tools”| Tool | Purpose |
|---|---|
ps, top, htop | List processes; zombies show as Z or defunct. |
strace -f | Trace fork, exec, exit. |
pstree | Parent–child tree. |
/proc/<pid>/status | State (e.g. Zombie). |
wait/waitpid | In code: reap children. |
kill | Send signal to parent (to force reap by killing parent). |
gdb, dmesg | Debug crashes; kernel messages. |
Using the tools
Section titled “Using the tools”- Parent–child tree —
pstree -pshows PIDs and hierarchy. - Trace fork/exec/exit —
strace -f -e fork,execve,exit_group ./programor attach to a running process. - Find zombies —
ps aux | grep Zorps -eo pid,state,comm | grep Z. Check parent withps -o ppid= -p <zombie_pid>. - Process state —
cat /proc/<pid>/status;State:shows running, zombie, etc. - Reaping in C — In the parent, call
waitpid(-1, &status, WNOHANG)in a loop or in a SIGCHLD handler to collect exit status and clear zombies.
Lifecycle flow
Section titled “Lifecycle flow”Parent | | fork() vChild | | exec(new_program) vRunning (new program) | | exit(status) vZombie (defunct) ----[ parent wait() ]----> Reaped (gone) | | If parent dies: reparent to init; init wait() reaps vReapedParent → fork → Child → exec → run → exit → zombie; parent wait() reaps. If parent dies first, init reaps the zombie.