【Linux学习笔记】僵尸进程、孤儿进程

僵尸进程

  • 僵尸状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读到子进程 退出的返回代码时就会产生僵尸进程。
  • 僵尸进程会 以终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。
  • 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。
我们创建一个维持30s的僵尸进程
#include <stdio.h>
#include <stdlib.h>

int main()
{
    pid_t id = fork();

    if(id < 0)
    {
        perror("fork");
        return 1;
    }   
    else if(id > 0) //parent
    {
        printf("parent[%d] id sleeping...\n", getpid());
        sleep(30);
    }
    else    //children
    {
        printf("child[%d] is begin Z...\n", getpid());
        sleep(5);
        exit(1);
    }

    return 0;
}

在另一个终端下启动监控

//监控命令行脚本
while : ; do ps aux|grep js |grep -v grep;sleep 1;echo "#############################"; done 

测试结果:

运行程序

开始监控

子进程变成僵尸进程
ptrace系统调用追踪进程运行

僵尸进程的危害
  • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样。可父进程如果一直不读取,那么子进程就一直是僵尸进程。
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct中,换言之,Z状态一直不退出,PCB需要一直维护着。
  • 如果一个父进程创建了很多子进程,就是不回收,就会造成资源浪费,因为数据结构本身就要占用内存。进而之就会造程内存泄露。

孤儿进程

  • 父进程先退出,子进程就称之为“孤儿进程”。
  • 孤儿进程被1号init进程领养,当然也由init进程回收
创建一个孤儿进程
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    pid_t id = fork();

    if(id < 0)
    {
        perror("fork");
        return 1;
    }
    else if(id == 0)    //child
    {
        printf("I am child,pid: %d\n", getpid());
        sleep(10);  
    }
    else
    {
        printf("I am parent,pid: %d\n", getpid());
        sleep(3);
        exit(1);
    }

    return 0;
}

运行程序
开始监控
由图可以看出,父进程退出后,子进程变成了孤儿进程

再来看下孤儿进程的ppid,变成1了,因此它被1号进程init领养了。

这里写图片描述
孤儿进程是没有父进程的进程,孤儿进程这个重任就落到了init进程身上,init进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。

猜你喜欢

转载自blog.csdn.net/lyjwonderful/article/details/80642289