Linux关于僵尸进程和孤儿进程深入

本文介绍了孤儿进程和僵尸进程的概念及影响。孤儿进程是指父进程结束后遗留下来的子进程,这类进程会被init进程接管并正常结束生命周期。僵尸进程则是指已终止但父进程未回收其资源的子进程,若不及时回收资源可能导致系统无法分配新的进程号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、孤儿进程
父进程运行结束,但子进程还在运行(未运行结束)的子进程就称为孤儿进程(Orphan Process)。

每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为 init ,而 init 进程会循环地 wait() 它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init 进程就会代表党和政府出面处理它的一切善后工作。

因此孤儿进程并不会有什么危害。

二、僵尸进程
进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。

这样就会导致一个问题,如果进程不调用wait() 或 waitpid() 的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害,应当避免。

上面描述了关于孤儿进程和僵尸进程的概念和可能造成的影响。下面以代码例子更加深入了解

1、正常场景
该场景会在父进程中通过waitpid等待回收子进程的资源,保证不会出现资源泄漏情况

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


int main()
{
    pid_t ppid, childPid;
    int status = 0;

    system("ps -aux | grep forkTest");
    printf("-------------------------\n");
    ppid = fork();

    if(ppid < 0)
    {
        perror("error in fork");
    } else if (ppid == 0)
    {
       printf("this is in child process, child process pid:%d\n",getpid());
       //sleep 3s and exit child process
       sleep(30);
       exit(0);
    } else{
       printf("this is in parent process, parent process pid:%d\n", getpid());
    }

    do{
        childPid = waitpid(ppid, &status, WNOHANG);
        if(childPid == 0)
        {
            printf("No child exited,ret=%d\n", childPid);
            sleep(2);
        }
    }while(childPid == 0);

    if(WIFEXITED(status))
        printf("normal exited:%d\n",childPid);
    if(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL)
        printf("process killed by signal SIGKILL\n");

    return 0;
}

2、僵尸进程

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


int main()
{
    pid_t ppid;
    ppid = fork();//创建进程
    
    if(ppid < 0)
    {
        perror("error in fork");`在这里插入代码片`
    } else if (ppid == 0)  //ppid为0则为子线程
    {
       printf("this is in child process, child process pid:%d\n",getpid());
       exit(0); //这里让子进程先退出,父进程没有回收子进程资源则会导致僵尸进程的出现
    } else{        //ppid>0则为父线程
       printf("this is in parent process, parent process pid:%d\n", getpid());
    }

    sleep(300); //这里sleep为了保证父进程后退出
	return 0;
}

结果分析如下:
在这里插入图片描述
为了防止僵尸进程的出现,应该在父进程中回收子进程退出后的资源,可以使用wait或者waitpid回收资源

3、孤儿进程

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


int main()
{
    pid_t ppid;
    ppid = fork();//创建进程
    
    if(ppid < 0)
    {
        perror("error in fork");
    } else if (ppid == 0)  //ppid为0则为子线程
    {
       printf("this is in child process, child process pid:%d\n",getpid());
       sleep(30); //这里睡眠30s为了保证子进程后于父进程退出
       exit(0); 
    } else{        //ppid>0则为父线程
       printf("this is in parent process, parent process pid:%d\n", getpid());
    }
	return 0;
}

该种情况会出现孤儿进程,但该孤儿进程会被系统init接管保证资源释放的工作,故孤儿进程并没有什么危害。

Linux 中,僵尸进程孤儿进程都是指与父进程不再有联系的进程,它们通常是由于进程管理不当或程序错误导致的。 **僵尸进程**是已经完成执行任务,但其父进程还没有来得及处理其退出状态的进程。当进程完成执行后,它的退出状态(也称为退出码或终止状态)会被保存在系统中,直到父进程通过 `wait` 或 `waitpid` 等函数来获取该状态。如果父进程没有处理该状态,那么该进程就会成为僵尸进程,占用系统资源。要清理僵尸进程,可以使用 `kill` 命令向其父进程发送 `SIGCHLD` 信号,或者重新编写程序,使其正确处理子进程的退出状态。 **孤儿进程**是指其父进程已经退出或被终止,但其自身仍在运行的进程孤儿进程会被 `init` 进程进程号为 `1`)接管,`init` 进程会定期检查系统中是否有孤儿进程,并且将其的父进程设置为 `init` 进程。要避免孤儿进程产生,可以在父进程退出之前,等待子进程的退出,或者将子进程的父进程设置为 `init` 进程。 可以使用 `ps` 命令来查看系统中的僵尸进程孤儿进程。使用以下命令可以查看所有僵尸进程: ``` ps aux | grep 'Z' ``` 其中,`aux` 选项用于显示所有进程,`grep 'Z'` 用于查找所有状态为 `Z` 的进程,即僵尸进程。 使用以下命令可以查看所有孤儿进程: ``` ps -ejH ``` 其中,`-e` 选项用于显示所有进程,`-j` 选项用于以层次结构的形式显示进程,`-H` 选项用于显示所有孤儿进程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值