fork 产生僵尸进程和孤儿进程

0 僵尸进程

    僵尸进程是指某进程已经退出,然后其父进程还没有调用wait(),waitpid()等对其进程退出处理(收尸),所以这种进程成为僵尸进程。


1 孤儿进程

    孤儿进程是其父进程在其之前退出,自己由init进程收养的进程。由于内核定义每一个进程必须要有父进程,所以内核对孤儿进程的处理是将其父进程设置为init进程。


2 fork()产生孤儿进程和僵尸进程

    话不多少,上code:    

#include <stdio.h>
#include <unistd.h>
void main(){
    pid_t pson1, pson2, pson3;
    int pp = 1;
    printf("\n");
    if((pson1 = fork())<0){
        printf("fork error. \n");
        exit(0);
    }   else if (pson1 == 0){ //son1
            sleep(1);
            printf("son1   pid: %d, my father pid %d\n", getpid(), getppid());
            if((pson2 = fork()) < 0){
                printf("fork error. \n");
                exit(0);
            }   else if (pson2 == 0){ //son2
                    sleep(1);
                    printf("son2   pid: %d, my father pid %d\n", getpid(), getppid());
                    sleep(2);   //wait son1 to exit();
                    printf("son2   pid: %d, my father pid %d\n", getpid(), getppid());
                    exit(0);
                }
                else {  //son1
                    sleep(2);
                    printf("son1   exit();\n");
                    exit(0);    //son1 exit(); 
                }
        }
        else{   //parent
            printf("father pid: %d, my father pid %d\n", getpid(), getppid());
            sleep(5);
            printf("father pid: %d, my father pid %d\n", getpid(), getppid());
        }
    exit(0);
}
root:~/apue/mycode# ./fork 

father pid: 5408, my father pid 5117
son1   pid: 5409, my father pid 5408
son2   pid: 5410, my father pid 5409
son1   exit();
son2   pid: 5410, my father pid 1
father pid: 5408, my father pid 5117
root:~/apue/mycode# echo $$
5117
root:~/apue/mycode#     

    在结果中我们可以看出,当前shell 的进程是 5117. 

    程序的主进程(下称为父进程)是5408.主进程fork()出子进程1(pson1)是5409.

    子进程1 fork()出子进程2(pson2)是5410.

    然后子进程1退出,子进程1变为僵尸进程;同时子进程2丢失父进程,变为孤儿进程。


    下为按时间分析程序执行情况:

    第0秒   在最开始,父进程进行第一次fork(),产生 pson1 进程。

    pson1 = fork()

        此时父进程打印一行信息,而pson1进程阻塞一秒,parent进程阻塞5s。

    father pid: 5408, my father pid 5117

    第1秒 pson1 阻塞结束,打印一行信息;然后pson1开始fork(),生成pson2,同时pson1 阻塞2s、pson2 阻塞1s。

    son1   pid: 5409, my father pid 5408

    第2秒 pson2 阻塞结束,打印自己的pid和ppid,然后pson2 阻塞2s。

    son2   pid: 5410, my father pid 5409

    第3秒 pson1 阻塞结束,打印退出信息,并退出进程。此时partent进程在阻塞中,未对其进程回收,所以pson1为僵尸进程

    son1   exit();

    第4秒 pson2 阻塞结束,打印自己的pid和ppid。可见其ppid已经是1了,所以此时pson2为孤儿进程

    son2   pid: 5410, my father pid 1

    第5秒 father进程阻塞结束,打印自己的pid和ppid。

    father pid: 5408, my father pid 5117

    第5秒后 father进程退出,pson1和pson2也被回收,僵尸进程和孤儿进程都被消失。


3 相关知识

    1 命令 ~ ps -ef |grep $(execname$ |grep -v grep  可以观察对应的进程情况。

    2 命令 ~ echo $$ 可以看当前bash的pid。

猜你喜欢

转载自blog.csdn.net/mistakk/article/details/80274323