进程状态详解

在Linux环境下,C语言可通过系统调用( fork() 、 wait() 、 sleep() 等)结合 /proc 文件系统模拟并查看进程状态,Linux中进程核心状态主要有运行/就绪态®、阻塞态(S)、僵尸态(Z)、暂停态(T),下面通过代码完整演示进程状态的转换过程,并详细解析各状态含义。

一、进程状态核心定义(Linux)

状态标识 含义 对应经典状态

R Running/Runnable 运行态/就绪态

S Sleeping(可中断) 阻塞态(I/O等待)

D Uninterruptible Sleep 阻塞态(不可中断)

Z Zombie 终止态(过渡)

T Stopped 暂停态

二、C语言代码实现:进程状态模拟

代码通过 fork() 创建子进程, sleep() 模拟阻塞, /proc/pid/status 读取进程状态,完整代码如下:

c 复制代码
  
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>

// 从/proc文件系统读取进程状态
void print_process_status(pid_t pid) {
    char status_path[64];
    FILE *fp;
    char line[256];
    // 拼接/proc下的进程状态文件路径
    snprintf(status_path, sizeof(status_path), "/proc/%d/status", pid);
    fp = fopen(status_path, "r");
    if (fp == NULL) {
        perror("fopen failed");
        return;
    }
    // 查找State行,提取进程状态
    while (fgets(line, sizeof(line), fp) != NULL) {
        if (strncmp(line, "State:", 6) == 0) {
            printf("进程(%d)当前状态:%s", pid, line + 7);
            break;
        }
    }
    fclose(fp);
}

// 子进程执行的任务,模拟不同状态转换
void child_process_task() {
    pid_t child_pid = getpid();
    printf("\n子进程(%d):创建完成,进入就绪态\n", child_pid);
    print_process_status(child_pid);

    // 模拟运行态:执行计算操作
    printf("子进程(%d):进入运行态,执行计算任务\n", child_pid);
    long long sum = 0;
    for (long long i = 0; i < 100000000; i++) {
        sum += i;
    }
    print_process_status(child_pid);

    // 模拟阻塞态:sleep模拟I/O等待(释放CPU)
    printf("子进程(%d):进入阻塞态,等待I/O(sleep 3秒)\n", child_pid);
    sleep(3);
    print_process_status(child_pid);

    // 再次进入运行态,完成任务
    printf("子进程(%d):回到运行态,计算结果:%lld\n", child_pid, sum);
    print_process_status(child_pid);

    // 执行完毕,进入终止态(若父进程未回收则为僵尸态)
    printf("子进程(%d):任务完成,进入终止态\n", child_pid);
    exit(0);
}

int main() {
    pid_t pid = fork(); // 创建子进程,子进程进入新建态
    if (pid < 0) {
        perror("fork failed");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程执行逻辑
        child_process_task();
    } else {
        // 父进程执行逻辑
        printf("父进程(%d):创建子进程(%d),子进程进入新建态\n", getpid(), pid);
        print_process_status(pid);

        // 等待子进程结束,避免子进程变成僵尸态
        wait(NULL);
        printf("\n父进程(%d):子进程已终止,回收其资源\n", getpid());
        // 子进程被回收后,/proc下的状态文件会消失,再次读取会报错
        print_process_status(pid);
    }
    return 0;
}
 
三、代码解析
  1. 新建态: fork() 调用成功后,子进程被创建,操作系统为其分配PID和内存资源,此时子进程处于新建态,等待系统调度。
  2. 就绪态:子进程创建完成后,进入就绪队列等待CPU调度, /proc 中状态显示为 R (running) (Linux中就绪和运行态统一用R标识)。
  3. 运行态:子进程获得CPU时间片后,执行计算循环,状态保持 R ,此时进程占用CPU执行指令。
  4. 阻塞态:调用 sleep(3) 模拟I/O等待,子进程释放CPU,状态变为 S (sleeping) (可中断阻塞态),直到sleep结束才重新进入就绪态。
  5. 终止态:子进程执行 exit(0) 后,若父进程未调用 wait() 回收,会进入 Z (zombie) 僵尸态;父进程调用 wait(NULL) 后,子进程资源被彻底回收,状态文件消失。
四、编译与运行
  1. 编译命令: gcc process_state.c -o process_state
  2. 运行命令: ./process_state
  3. 额外查看:可在另一个终端执行 ps -aux | grep process_state ,实时观察进程状态变化。
相关推荐
忆挽篱笙歌13 分钟前
gcc,g++
linux
l1t1 小时前
修复WSL CreateInstance/E_UNEXPECTED和 mounted read-only 错误
linux·windows·wsl
Ruiery1 小时前
Linux 6.6内核 CPU 深度解析(九):时钟与 TSC — 内核怎么从 PIT/HPET 切到 TSC
linux·运维·服务器
吴声子夜歌1 小时前
Nginx应用与运维——Nginx日志管理
java·运维·nginx
打工仔折腾 AI2 小时前
用UU远程把家里电脑变成AI Agent常驻服务器:CLI、端口映射与代理实测
运维·服务器·人工智能·后端·python·电脑·ai agent 实战
91刘仁德2 小时前
Linux网络编程从入门到实战:UDP/TCP协议与socket编程全解析
linux·网络·笔记·tcp/ip·udp
guo_wen_qiang2 小时前
云服务器nacos搭建-集群&持久化
java·运维·服务器
水饺编程2 小时前
第1章:下载 Linux 0.12 内核
linux·c语言·汇编·ubuntu
牢姐与蒯2 小时前
一点小碎片——每个线程独有的东西——上下文+栈
linux·运维·服务器
小此方2 小时前
Linux网络(二十):TCP拥塞控制与延迟应答详解:从拥塞窗口到TCP性能优化,理解TCP与UDP的效率差异
linux·网络·php