Linux Process States: Running, Sleeping, Stopped

This article provides an overview of how the Linux operating system manages process lifecycles through distinct operational states. It covers the internal mechanisms used by the Linux kernel—specifically the scheduler, task structures, and signals—to transition processes between running, sleeping, and stopped states, ensuring efficient CPU utilization and system stability.

Process Representation in the Linux Kernel

In Linux, every process is represented by a core data structure called task_struct, often referred to as the Process Control Block (PCB). Defined in the kernel's sched.h header file, the task_struct contains all vital metadata about a process, including its identifier (PID), memory maps, open file descriptors, CPU context, and its current execution state.

The kernel tracks execution states via a bitmask field (typically __state or state) within the task_struct. The scheduler continually inspects and updates this field to decide which task should execute on an available CPU core.

The Running State (TASK_RUNNING)

A process marked as TASK_RUNNING is either actively executing on a CPU core or sitting in a run queue waiting for CPU time.

The Sleeping State

When a process must wait for an event—such as disk I/O, network data, user input, or a lock release—it releases the CPU and enters a sleeping state. The kernel places the process onto a wait queue associated with the specific resource. Linux divides sleep into two primary categories:

1. Interruptible Sleep (TASK_INTERRUPTIBLE)

This is the most common sleeping state. The process sleeps while waiting for a hardware event or resource availability. However, it can be interrupted before the event occurs if it receives an asynchronous signal (such as SIGINT or SIGKILL). When a signal arrives, the kernel wakes the process, transitions it back to TASK_RUNNING, and directs it to execute the signal handler.

2. Uninterruptible Sleep (TASK_UNINTERRUPTIBLE)

In this state, commonly indicated by the D state code in utilities like ps and top, the process waits directly for critical hardware operations (such as direct disk I/O or NFS queries). The kernel ignores all incoming signals while the process is in this state to prevent data corruption or inconsistent kernel structures. The process will not wake up until the hardware event completes or the underlying driver returns a result.

The Stopped State (TASK_STOPPED and TASK_TRACED)

A process enters a stopped state when its execution is suspended explicitly, either by a user command or another process.

State Transitions and Kernel Coordination

State transitions are driven by kernel interrupts, system calls, and signals:

  1. Running to Sleeping: A process issues a blocking system call (e.g., read()). The kernel moves the task from the run queue to an I/O wait queue and changes the state to TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE.
  2. Sleeping to Running: When the hardware interrupt fires signaling that data is ready, the interrupt handler moves the task_struct off the wait queue and back into the scheduler's run queue, restoring its state to TASK_RUNNING.
  3. Running to Stopped: The kernel intercepts a signal like SIGSTOP, removes the task from the run queue, and sets the state to TASK_STOPPED.
  4. Stopped to Running: Receipt of SIGCONT clears the stopped status, places the process back onto the run queue, and marks it as TASK_RUNNING.

By systematically managing these state flags and associated execution queues, the Linux kernel multiplexes hardware resources across thousands of concurrent tasks without conflict.