linux下僵尸进程和孤儿进程

21 篇文章 1 订阅

子进程是通过父进程创建的,子进程也可以继续创建子进程。父进程无法预测子进程到底什么时候结束,当一个子进程结束之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。

僵尸进程 :
子进程结束了,但是父进程没有调用wait()或者waitpid()取得子进程的终止状态,这个子进程将变成一个僵尸进程。
利用命令ps,可以看到有标记为Z的进程就是僵尸进程。
僵尸进程危害:
系统中的进程数量是有限的,虽然僵尸进程占用的资源和内存都比较少,但是它却占领着数字,可能会导致系统无法再创建新的进程,因此及时清除僵尸进程很重要!

避免僵尸进程:

1、通过信号机制,子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait进行处理僵尸进程。

  1. 两次fork()
    原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程。

处理僵尸进程:
把父进程杀掉。父进程死后,僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程。它产生的所有僵尸进程也跟着消失。

构造僵尸进程,子进程退出,父进程未退出,未wait

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

int main ()
{
    pid_t fpid;
    fpid = fork();//返回的是子进程id,在子进程中,这个值为0
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0) {
        printf("i am the child process, my process id is %d parentid %d \n",getpid(), getppid());
        printf("the child process exit\n");
        exit(0);
    }
    else {
        printf("i am the parent process, my process id is %d my child process %d\n",getpid(), fpid);
        sleep(60);
    }
    return 0;
}

使用信号解决

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void sig_child(int signo)
{
    pid_t pid;
    int stat;
    while ((pid = waitpid(-1, &stat, WNOHANG))>0)
    printf("child %d exit\n", pid);
}

int main ()
{
    pid_t fpid;
    signal(SIGCHLD,sig_child);
    fpid = fork();//返回的是子进程id,在子进程中,这个值为0
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0) {
        printf("i am the child process, my process id is %d parentid %d \n",getpid(), getppid());
        printf("the child process exit\n");
        exit(0);
    }
    else {
        printf("i am the parent process, my process id is %d my child process %d\n",getpid(), fpid);
        sleep(60);
    }
    return 0;
}

两次fork解决,第二个子进程为孤儿进程

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

int main ()
{
    pid_t fpid;
    fpid = fork();//返回的是子进程id,在子进程中,这个值为0
    if (fpid < 0)
        printf("error in fork!\n");
    else if (fpid == 0) {
        printf("i am the first child process, i will fork\n");
        fpid = fork();
        if(0 > fpid){
            printf("error in fork!\n");
        }else if (fpid == 0){
            printf("i am the second child process\n");
            sleep(30);
            printf("i am the second child process, my process id is %d parentid %d \n",getpid(), getppid());
        }else{
            printf("i am the first child process, i will exit\n");
            sleep(1);
            exit(0);
        }
    }
    else {
        printf("i am the parent process, my process id is %d my child process %d\n",getpid(), fpid);
        if (waitpid(fpid, NULL, 0) != fpid){
            perror("waitepid error:");
            exit(1);
        }
        exit(0);
    }
    return 0;
}

孤儿进程:父进程先与子进程结束,子进程就由Init(进程号为1)来接管他,成为他的父进程,此时称这个进程为孤儿进程,其状态收集工作由init进程负责。
孤儿进程并不会有什么危害。

构造孤儿进程,父进程退出,子进程未退出

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

int main ()
{
    pid_t fpid;
    fpid = fork();//返回的是子进程id,在子进程中,这个值为0
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0) {
        printf("i am the child process, my process id is %d parentid %d \n",getpid(), getppid());
        sleep(2);
        //这里父进程id为1   ps -fu$USER查看也是如此
        printf("i am the child process, my process id is %d parentid %d \n",getpid(), getppid());
        sleep(20);
    }
    else {
        printf("i am the parent process, my process id is %d my child process %d\n",getpid(), fpid);
        sleep(1);
    }
    return 0;
}

守护进程(Daemon)是在一类脱离终端在后台执行的程序, 通常以 d 结尾, 随系统启动, 其父进程 (ppid) 通常是 init 进程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值