第7章 进程关系(1)_守护、孤儿和僵尸进程

时间:2023-01-30 04:21:50

 1. 守护、孤儿和僵尸进程

(1)守护进程

  ①守护进程(daemon)是生存期长的一种进程。它们常常在系统引导装入时启动,在系统关闭时终止。

  ②所有守护进程都以超级用户(用户ID为0)的优先权运行。

  ③守护进程没有控制终端

  ④守护进程的父进程都是init进程(1号进程)。

(2)孤儿进程父进程先结束,子进程就成为孤儿进程,会由1号进程(init进程)领养

【编程实验】产生孤儿进程

//process_orphen.c

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

//孤儿进程。演示时启动另一个终端登录来查看子进程的状态
//由于父进程先结束,子进程会由init进程领养。

int main(void)
{
    pid_t pid = fork();
    if(pid < 0){ 
        perror("fork error");
        exit(1);
    }else if(pid > 0){ //parent process
        printf("%d deaded\n", getpid());
        exit(0); //父进程终止
    }else{
        sleep(4); //让父进程先终止,子进程变成孤儿进程,会由1号进程领养
        printf("pid: %d, ppid: %d\n", getpid(), getppid());//ppid=1
    }   

    return 0;
}

(3)僵尸进程

  ①如果子进程先结束父进程还存在。这时子进程并没有被完全释放内存(在内核中的task_struct没被释放),该进程就成为僵尸进程

  ②当僵尸进程的父进程结束后就会被init进程领养,最终被回收。

  ③避免僵尸进程的方法:

    A.让僵尸进程的父进程来回收,父进程每隔一段时间来查询子进程是否结束并回收。调用wait或waitpid,通知内核释放僵尸进程。

    B.采用信号SIGCHLD通知处理,并在信号处理程序中调用wait函数来通知释放僵尸进程。

    C.让僵尸进程成为孤儿进程,由init进程回收。

【编程实验】僵尸进程的产生

//process_zombie.c

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

int main(void)
{
    pid_t pid = fork();  
    if((pid) < 0){
        perror("fork error");
        exit(1);
    }else if(pid == 0){//child process
        printf("pid: %d, ppid: %d\n", getpid(), getppid());
        exit(0);
    }

    //等待子进程结束并通知释放task_struct
    //wait(0);  //加上这句会通知内核释放子进程的task_struct,不会
                //产生僵尸进程,可以取消注释来对比。

    //试图产生僵尸进程
    while(1){ //父进程继续循环,不退出。此时子进程未被完全
              //释放而成为僵尸进程
        sleep(1);
    }

    return 0;
}