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.
- Execution: On a multi-core system, multiple processes can be simultaneously in this state, executing instructions on separate cores.
- Ready to Run: If all CPU cores are occupied,
processes in
TASK_RUNNINGreside in the scheduler's run queue (managed by schedulers such as the Completely Fair Scheduler or CFS). - Preemption and Context Switching: When a process’s
allocated time slice expires or a higher-priority process becomes
runnable, the kernel triggers a context switch. The register states and
program counter of the current process are saved into its
task_struct, and the CPU switches to the next task in the queue.
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.
TASK_STOPPED: Triggered when the process receives a stop signal, such asSIGSTOP,SIGTSTP(sent viaCtrl+Zin a terminal),SIGTTIN, orSIGTTOU. In this state, the process remains in memory but is removed from the run queues completely. It will not receive CPU time until it receives a resume signal, specificallySIGCONT.TASK_TRACED: A specialized stopped state used during debugging. When a process is monitored by tools likegdbvia theptracesystem call, the kernel pauses the process at breakpoints or step executions, marking it as traced.
State Transitions and Kernel Coordination
State transitions are driven by kernel interrupts, system calls, and signals:
- 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 toTASK_INTERRUPTIBLEorTASK_UNINTERRUPTIBLE. - Sleeping to Running: When the hardware interrupt
fires signaling that data is ready, the interrupt handler moves the
task_structoff the wait queue and back into the scheduler's run queue, restoring its state toTASK_RUNNING. - Running to Stopped: The kernel intercepts a signal
like
SIGSTOP, removes the task from the run queue, and sets the state toTASK_STOPPED. - Stopped to Running: Receipt of
SIGCONTclears the stopped status, places the process back onto the run queue, and marks it asTASK_RUNNING.
By systematically managing these state flags and associated execution queues, the Linux kernel multiplexes hardware resources across thousands of concurrent tasks without conflict.