Linux Process State
Contents
进程状态机
最近在看南京大学蒋炎岩老师的 2025 操作系统课程。里面有一句话, 计算机中的一切程序可以视为 state machine。很有启发。进程有初始状态, CPU 这个无情的执行指令的机器执行一条指令后,程序的状态就发生了变化。
process state
Running/Runnable(R)
万事俱备,只需要被 scheduler 调度到 CPU 上去运行。
Interruptable Sleep(S)
处于这个状态的不会被 scheduler 调度到 CPU 上去运行。
d_state.c code
#include <unistd.h>
int main(){
pause();
}
- gcc -o d_state d_state.c
- ./d_state
- ps aux | grep d_state
Uninterruptible Sleep(D)
可能是 Disk Sleep 的原因。状态用 D 表示。
Stopped(T)
如使用 SIGSTOP 信号,暂停的进程。
d_state.c code
#include <unistd.h>
int main(){
pause();
}
- gcc -o d_state d_state.c
- ./d_state
- ps aux | grep d_state
- kill -SIGTSTP $(pidof d_state)
- ps aux | grep d_state
Zombie(Z)
进程已经执行了 exit, exit code 还没有被父进程 wait/waitpid 读取。也就是进程的 PCB 还没有从 kernel 的 process table 中清除。
zombie.c code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
int main() {
pid_t child_pid = fork();
if (child_pid == 0) { // Child process
printf("Child PID: %d\n", getpid());
exit(0); // Child exits immediately
} else { // Parent process
printf("Parent PID: %d\n", getpid());
printf("Child PID: %d\n", child_pid);
printf("Parent is sleeping (check for zombie with `ps`).\n");
sleep(30); // Parent sleeps (does not call wait())
printf("Parent exiting.\n");
}
return 0;
}
- gcc -o zombie zombie.c
- ./zombie
- ps aux | grep zombie
system calls changing process state on Linux
fork()
• Purpose: Creates a new child process by duplicating the parent process.
• State Change: The child starts in the ready/runnable state (waiting for CPU time).
• Parameters: None.
• Return Value:
• 0 to the child process.
• Child's PID to the parent.
• -1 on error.
• Example: Used in spawning new processes (e.g., shell commands).
execve()
• Purpose: Replaces the current process’s memory space with a new program.
• State Change: The process remains in the running state but executes new code.
• Parameters:
• path: Path to the executable.
• argv: Command-line arguments.
• envp: Environment variables.
• Return Value: Only returns on error (-1).
• Example: Running programs like ls or grep from a shell.
exit() / _exit()
• Purpose: Terminates the current process.
• State Change: Moves the process to zombie (until the parent calls wait()).
• Parameters:
• status: Exit status code.
• Return Value: None (does not return).
• Difference: exit() flushes buffers; _exit() is a raw system call.
• Example: Clean termination after program completion.
wait() / waitpid()
• Purpose: Suspends the parent until a child changes state (exits or stops).
• State Change: Parent enters sleeping state until child exits.
• Parameters:
• status: Stores child’s exit status.
• pid: Specific child to wait for (in waitpid).
• Return Value: Child PID on success; -1 on error.
• Example: Parent process ensuring a child completes first.
kill() / raise()
• Purpose: Sends signals to processes (e.g., SIGTERM, SIGSTOP).
• State Change:
• SIGSTOP: Moves process to stopped state.
• SIGCONT: Resumes a stopped process.
• SIGKILL: Terminates immediately.
• Parameters:
• pid: Target process ID.
• sig: Signal to send.
• Return Value: 0 on success; -1 on error.
• Example: Terminating a frozen process via kill -9 PID.
pause()
• Purpose: Suspends the process until a signal is received.
• State Change: Process enters interruptable sleeping state.
• Parameters: None.
• Return Value: Always -1 (interrupted by signal).
• Example: Waiting indefinitely for user input or signals.
nanosleep()
• Purpose: Pauses execution for a specified time.
• State Change: Process enters interruptible sleep.
• Parameters:
• req: Time to sleep.
• rem: Remaining time if interrupted.
• Return Value: 0 on success; -1 on error.
• Example: High-precision delays in real-time applications.
ptrace()
• Purpose: Allows a process to control another (debugging, tracing).
• State Change: Traced process enters stopped state on signals.
• Parameters:
• request: Action (e.g., PTRACE_ATTACH, PTRACE_CONT).
• pid: Target process ID.
• Return Value: Varies by request; -1 on error.
• Example: Debuggers like gdb using breakpoints.
clone()
• Purpose: Creates a child process or thread with configurable behavior.
• State Change: New process/thread starts in ready state.
• Parameters:
• fn: Function for the child to execute.
• flags: Options (e.g., CLONE_VM for shared memory).
• arg: Arguments for fn.
• Return Value: Child PID on success; -1 on error.
• Example: Implementing threads (used by pthread library).
sched_yield()
• Purpose: Voluntarily yields the CPU to other processes/threads.
• State Change: Process moves from running to ready state.
• Parameters: None.
• Return Value: 0 on success; -1 on error.
• Example: Cooperative multitasking in real-time apps.
exit_group()
• Purpose: Terminates all threads in a process.
• State Change: All threads enter zombie state.
• Parameters:
• status: Exit code.
• Return Value: Does not return.
• Example: Terminating multi-threaded applications.
Key Signals Affecting Process State
• SIGSTOP: Forcefully stops a process.
• SIGCONT: Resumes a stopped process.
• SIGTERM: Requests graceful termination.
• SIGKILL: Forcefully kills a process.
Summary Table
| System Call | Purpose | Key State Change |
|---|---|---|
fork() |
Create child process | Child → Runnable |
execve() |
Replace process image | Process runs new code |
exit() |
Terminate process | Process → Zombie |
wait() |
Wait for child state change | Parent → Sleeping |
kill() |
Send signal (e.g., stop/resume) | Target → Stopped/Running |
pause() |
Sleep until signal | Process → Sleeping |
ptrace() |
Debug/trace another process | Target → Stopped |
clone() |
Create thread/process | New entity → Runnable |
These system calls and signals form the backbone of process lifecycle management in Linux, enabling creation, termination, synchronization, and debugging of processes.