Linux进程状态解析:僵尸与孤儿进程揭秘

文章目录

  • 1.进程状态
    • 1.1 linux内核源码定义
    • 1.2 进程状态查看
  • 2.僵尸进程
  • 3.孤儿进程
  • 4.僵尸进程危害

1.进程状态

1.1 linux内核源码定义

cpp 复制代码
/*
*The task state array is a strange "bitmap" of
*reasons to sleep. Thus "running" is zero, and
*you can test for combinations of others with
*simple bit tests.
*/
static const char *const task_state_array[] = {
    "R (running)",     /*0 */
    "S (sleeping)",    /*1 */
    "D (disk sleep)",  /*2 */
    "T (stopped)",     /*4 */
    "t (tracing stop)",/*8 */
    "X (dead)",        /*16 */
    "Z (zombie)",     /*32 */
};

Linux内核定义了一个字符指针数组 task_state_array,用于表示Linux内核中进程的不同状态。每个状态对应一个位掩码值(如0、1、2、4等),可通过位运算检测组合状态。
R (running) - 运行中
状态值:0
进程正在CPU上执行或处于就绪队列等待调度。这是唯一非睡眠状态,其他状态均为阻塞/睡眠的变体。

S (sleeping) - 可中断睡眠
状态值:1
进程等待事件完成(如I/O操作),可被信号中断。此时进程不消耗CPU资源,当事件发生后会被移回运行队列。

D (disk sleep) - 不可中断睡眠
状态值:2
通常发生在等待磁盘I/O时,进程不可被信号中断。这是保证数据完整性的关键状态,常见于文件系统操作。

T (stopped) - 暂停状态
状态值:4
进程被信号(如SIGSTOP)暂停执行,可通过SIGCONT信号恢复。调试器常用此状态控制进程执行流程。

t (tracing stop) - 跟踪暂停
状态值:8
调试时由ptrace系统调用触发的特殊暂停状态,与T状态类似但专用于调试器跟踪场景。

X (dead) - 死亡状态
状态值:16
进程已完全终止,其资源尚未被父进程回收。该状态是瞬时状态,通常不可被用户空间观察到。

Z (zombie) - 僵尸状态
状态值:32
进程已终止但保留进程描述符(存放于PCB中),等待父进程读取退出状态。若父进程未正确处理会导致资源泄漏/内存泄漏

1.2 进程状态查看

bash 复制代码
ps aux /ps axj

a: 显示一个终端所有进程,包括其他用户的进程

x: 显示没有控制终端的进程,例如后台运行的守护进程

j:  显示进程归属的进程组ID,会话ID,父进程ID,以及与作业控制相关的信息

u: 以用户为中心的格式显示进程信息,提供进程的详细信息,如用户、CPU和内存使用情况

2.僵尸进程(有害)

僵尸进程是指已完成执行(已终止)但仍在进程表中保留条目(未被父进程回收资源)的子进程。其核心特点是进程本身已结束,但系统仍保留其部分信息(如进程ID、退出状态等),等待父进程处理。

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程
        printf("子进程PID:%d,运行2秒后退出\n", getpid());
        sleep(2);
        exit(0); // 子先死,父没wait
    } else {
        // 父进程
        printf("父进程PID:%d,休眠10秒(不wait收尸)\n", getpid());
        sleep(10); // 父不睡死,子变僵尸
        printf("父进程醒了,退出\n");
    }
    return 0;
}
    1. gcc zombie.c -o zombie && ./zombie
    1. 另开终端查僵尸(状态Z就是僵尸)
      ps -aux | grep Z
      子进程退出后,父没wait(回收),这8秒内子进程状态是Z(僵尸),占用PID资源

3.孤儿进程(无害)

孤儿进程是指父进程已终止或退出,但子进程仍在运行的进程。由于父进程不再存在,孤儿进程会被系统的 init 进程(进程ID为1)接管,由 init 负责后续的资源回收。

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程
        printf("子进程PID:%d,父进程PID:%d\n", getpid(), getppid());
        sleep(5); // 等父进程先退出
        printf("父进程已死,子进程新父PID:%d(变成1)\n", getppid());
    } else {
        // 父进程
        printf("父进程PID:%d,马上退出\n", getpid());
        exit(0); // 父进程先挂
    }
    return 0;
}
  • 孤儿进程会持续占用系统资源(如内存、CPU),直到被 init 回收。
  • 无直接危害:与僵尸进程不同,孤儿进程不会导致资源泄漏,最终会被系统清理。

4.僵尸进程危害

  1. 进程运行结束后,内核不会立刻删除它在进程表(所有PCB的集合****) 里的条目,而是保留进程 ID(PID)、退出状态等信息,等待父进程调用 wait()/waitpid() 来 "收尸"。这段时间里,这个只剩 "尸体" 的进程就是僵尸进程。它已经不占用 CPU、内存等运行资源,但会占用一个 PID 和进程表项。

2. 核心危害:耗尽 PID 与进程表(内存泄漏)

系统的PID 数量是有限的(比如 Linux 默认最大 PID 是 32768),进程表的容量也有限。

如果父进程一直不调用 wait(),大量僵尸进程会持续占用 PID 和进程表项。当 PID 被耗尽、进程表满了之后,系统无法再创建新的进程------ 比如无法启动新程序、无法打开新终端,甚至系统服务会崩溃。

3. 其他间接影响

进程表是内核频繁访问的数据结构,大量僵尸进程会增加内核遍历进程表的开销,轻微降低系统性能。排查问题时,僵尸进程会干扰进程状态的判断,增加运维复杂度。

相关推荐
活蹦乱跳酸菜鱼2 小时前
Linux开发板使用AI-通义千问
linux·运维·服务器
Xの哲學2 小时前
Linux IPC机制深度剖析:从设计哲学到内核实现
linux·服务器·网络·算法·边缘计算
lihui_cbdd2 小时前
[故障排查] NFS 存储集群卡顿的完整排查记录:谁在深夜疯狂读写?
linux·运维
张火火isgudi2 小时前
VMware Debian 挂载 Windows 文件夹至 Debian 目录
linux·运维·windows·debian
石榴花上3 小时前
银河麒麟上的9090端口被占用问题处理
linux
代码游侠3 小时前
学习笔记——sqlite3 数据库基础
linux·运维·网络·数据库·笔记·学习·sqlite
QT 小鲜肉3 小时前
【Linux命令大全】001.文件管理之od命令(实操篇)
linux·运维·服务器·chrome·笔记
Ronin3053 小时前
多路转接epoll
linux·网络·多路转接·高效io·epoll模型
珂玥c3 小时前
virsh启用linux虚拟机+忘记密码的操作
linux·运维·服务器