进程状态详解

在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 ,实时观察进程状态变化。
相关推荐
linux kernel17 小时前
第六部分:数据链路层
服务器·网络
聆风吟º21 小时前
CANN开源项目深度实践:基于amct-toolkit实现自动化模型量化与精度保障策略
运维·开源·自动化·cann
Coder个人博客21 小时前
Linux6.19-ARM64 mm mmu子模块深入分析
大数据·linux·车载系统·系统架构·系统安全·鸿蒙系统
较劲男子汉1 天前
CANN Runtime零拷贝传输技术源码实战 彻底打通Host与Device的数据传输壁垒
运维·服务器·数据库·cann
Doro再努力1 天前
Vim 快速上手实操手册:从入门到生产环境实战
linux·编辑器·vim
wypywyp1 天前
8. ubuntu 虚拟机 linux 服务器 TCP/IP 概念辨析
linux·服务器·ubuntu
风流倜傥唐伯虎1 天前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
Doro再努力1 天前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
senijusene1 天前
Linux软件编程:IO编程,标准IO(1)
linux·运维·服务器
不像程序员的程序媛1 天前
Nginx日志切分
服务器·前端·nginx