使用代码模拟实现僵尸进程, 孤儿进程

在进程运行时,由于某些原因会产生僵尸进程和孤儿进程,僵尸和孤儿两个词语形象的体现某进程的运行状态

僵尸进程:当进程加载到内存中时,需要向操作系统申请资源,正常情况下,当一个进程正常退出时,这个进程的资源会被他的父进程或者操作系统回收,如果这些资源在进程退出时没有被操作系统回收,就像一具已经僵硬的尸体,没人处理,形象的称这个进程为僵尸进程,如果僵尸进程一直不被回收,就造成了内存泄漏,试想一下,如果系统中的僵尸进程越来越多,操作系统自己的资源就越来越少,直到系统崩溃,下面模拟一下这种情况:

#include<stdio.h>
#include<unistd.h>

int main() {
    
    pid_t pid = fork();    
    if(pid < 0) {
        perror("fork");
        return 1;
    }
    else if(pid == 0) {
        //子进程
        printf("我是子进程~~\n");
        sleep(3);
        printf("子进程退出~~\n");
    }
    else {
        //父进程
        printf("我是父进程~~\n");
        sleep(5);
        printf("父进程异常退出~~\n");
		exit(1);
    }

    return 0;
}

运行结果:


在另一个窗口写一个监测a.out进程的shell脚本:while :;do ps aux | grep a.out | grep -v grep; sleep 1; echo "--------------------------------------------";done   在程序运行之后,监测到有这个进程如下图


在三秒后,子进程退出,这时父进程正在做自己的事情,子进程处于僵尸状态,正在等待父进程查看他的退出码,但在五秒之后父进程异常退出,异常退出的父进程应该没有能力去处理僵尸状态的子进程,但是发现在父进程结束之后,子进程也随即消失,为什么???,这个问题在孤儿进程之后回答


孤儿进程:假如一个父进程创建了一个子进程,父进程先退出,子进程就变成了孤儿进程,下面模拟一下孤儿进程:

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main() {
    
    pid_t pid = fork();    
    if(pid < 0) {
        perror("fork");
        return 1;
    }
    else if(pid == 0) {
        //子进程
        printf("我是子进程~~\n");
        pid_t ppid = getppid();
        printf("c: my ppid :%d\n", ppid);
        sleep(5);
        ppid = getppid();
        printf("c: my ppid :%d\n", ppid);
        printf("子进程退出~~\n");
    }
    else {
        //父进程
        printf("我是父进程~~\n");
        sleep(3);
        printf("父进程退出~~\n");
    }

    return 0;
}

实验结果:


就算子进程变成了孤儿进程,但是当他退出时,资源依然需要被父进程回收,不然就变成了僵尸进程,其实情况也没有那么悲观,当一个子进程的父进程退出后,该子进程就会被操作系统的1号进程领养,当这个子进程退出时,他的资源就由操作系统回收

那么僵尸进程的资源如何回收?

1.子进程结束后,操作系统会发送SIGCHLD信号给父进程,父进程收到这个信号以后,执行waitpid()函数来回收子进程的资源

2.如果父进程异常退出,僵尸进程成为"孤儿进程",过继给1号进程init,1号进程就会回收这个子进程的资源


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章