COMP 10024 – The UNIX Process Life-Cycle (Week 7)

March 3, 2026 5:59 pm Published by

In our previous sessions, we explored the static world of files and permissions. Today, we move into the dynamic world of the UNIX Kernel. If the file system is a library, then a process is a person currently reading a book. One is storage; the other is action.


1. What exactly is a Process?

A process is a single running copy of a program. It is important to distinguish between the two:

  • Program: A static file sitting on your disk (e.g., /bin/ls).
  • Process: The active execution of that file in the system’s memory.

UNIX uses an abstraction called “Virtual Memory.” This means that every process thinks it has the entire system to itself. It doesn’t know about other processes; the Kernel acts as the ultimate mediator, slicing up CPU time and memory so quickly that every process feels like it is the only one running.


2. The Ancestry: Parents and Children

In UNIX, processes are organized in a strict hierarchy. No process is “born” out of thin air.

  • The Rule of One: Every process has exactly one parent process.
  • The Rule of Many: A process can have zero, one, or many child processes.
  • The Ancestor (PID 1): This hierarchy starts with a process called init (or systemd in modern Linux). It is the first process started by the Kernel and is the “great-grandparent” of every other process on the system.
Term Definition
PID Process ID: A unique integer assigned to every process.
PPID Parent Process ID: The ID of the process that created it.
UID User ID: The user account that the process is running as.

3. The “Fork and Exec” Model

How do we actually create a new process? UNIX uses a two-step “copy and replace” mechanism.

Step 1: Forking

When a parent process needs to start a task, it performs a fork(). This creates a child that is an exact duplicate of the parent. The child inherits the same memory, the same open files, and the same variables. The only difference is a single “flag” that tells the process “You are the child.”

Step 2: Executing (Exec)

Usually, we don’t want two identical processes. The child then performs an exec(). This wipes the child’s memory and replaces it with a new program. For example, when you type ls in Bash, Bash forks a copy of itself, and that copy execs the ls program.


4. The End of the Road: Exit and Wait

A process dies when its program finishes or it is killed. But even in death, a process has one last job: telling its parent its “life story.”

  • Exit Code: When a process finishes, it returns a single integer to the parent.
    • 0 usually means “Success.”
    • Any non-zero number (1-255) usually indicates an error.
  • Waiting: A parent process should be waiting (using the wait() system call) to receive this exit code. Once the parent acknowledges the exit code, the process is completely removed from the system’s memory.

5. The Undead: Zombies and Orphans

What happens when the parent-child relationship breaks down? We get two unique “anomalies”:

Anomaly Description
Zombie (Defunct) A child process that has died, but the parent hasn’t “waited” for its exit code yet. It exists only as an entry in the process table, taking up no CPU or RAM.
Orphan A child process whose parent has died. In UNIX, orphans are immediately “adopted” by PID 1 (init), which properly cleans them up when they finish.

6. Inspecting the System

You can see this life-cycle in action using several built-in UNIX commands. Try typing these into your terminal:

  • ps: Shows a snapshot of current processes. Use ps aux or ps -ef for a full detailed list.
  • pstree: Visually displays the parent-child relationships in a tree format.
  • top: Provides a real-time, dynamic view of the most active processes.

Pro Tip: If you see a process listed with <defunct> in the ps output, you’ve found a Zombie!


Lab: Managing the UNIX Process Life-Cycle

In this lab, we shift our focus from static files to the active, living entities within UNIX: Processes. You will learn how to monitor, manage, and terminate processes while observing the parent-child relationships that define the system’s hierarchy.


Part 1: Snapshot and Real-Time Monitoring

The first step in process management is seeing what is actually running. We use two main tools: ps for a snapshot and top for a live feed.

  1. The Basic Snapshot: Type ps in your terminal.Observation: You will likely only see your current shell (bash) and the ps command itself.
  2. The Big Picture: To see every process running on the system, type:ps aux
    • a: Show processes for all users.
    • u: Display the user/owner column.
    • x: Show processes not attached to a terminal.
  3. Live Monitoring: Type top. This is the “Task Manager” of UNIX. Notice how the processes at the top shift as they consume CPU cycles. Press ‘q’ to exit.

Part 2: The Fork and Exec in Action

When you run a command, your shell forks a child. Let’s create a process that lasts long enough for us to inspect it.

  1. Run a “long-running” command: sleep 1000.Notice: Your terminal is now “blocked.” You cannot type new commands because the shell is waiting for the child to exit.
  2. Press Ctrl + C. This sends an Interrupt signal (SIGINT) to the process, killing it and returning control to your shell.

Part 3: Backgrounding and Job Control

Sometimes you want a process to run without blocking your terminal. This is known as “backgrounding” the task.

  1. Start a task in the background using the ampersand:sleep 2000 &Output: You will see a number like [1] 12345. The [1] is the Job ID and 12345 is the PID.
  2. List your active jobs: jobs
  3. Bring the task back to the foreground: fg %1. Now the terminal is blocked again.
  4. Suspend it (don’t kill it): Press Ctrl + Z. This sends the SIGSTOP signal. The process is now “Stopped.”
  5. Resume it in the background: bg %1.

Part 4: Terminating Processes (The Kill Command)

If a process is behaving badly or you simply want to end it, you use the kill command. In UNIX, kill is a way to send signals to a process.

  1. Identify the PID of your sleep process: ps | grep sleep
  2. Send a polite termination signal: kill [PID] (Replace [PID] with your actual number).
  3. Check jobs to see if it is gone. If a process refuses to die, use the “Sure Kill” (SIGKILL): kill -9 [PID].

Part 5: Investigating the “Life Story” (Exit Codes)

Every process ends with an integer code. In Bash, the special variable $? stores the exit code of the last command run.

  1. Run a successful command: ls /Check the exit code: echo $? (Should be 0).
  2. Run a command that fails: ls /non_existent_folderCheck the exit code: echo $? (Should be non-zero, indicating an error).

Part 6: Visualizing the Ancestry

To see how your shell is the parent of your commands, use pstree.

  1. Run: pstree -p [Your_Username]
  2. Look for bash. You should see it as a branch, and if you have background jobs running, they will appear as “children” stemming from that bash branch.

Summary Challenge: Find a Zombie

Zombies are processes that have finished but haven’t been “reaped” by their parents. To find them, run:

ps aux | grep 'Z'

In the “STAT” column, a Z indicates a defunct/zombie process. If you find one, try to identify its parent PID (PPID) using ps -el!

Categorised in: , ,

This post was written by amax

Comments are closed here.