僵尸进程/孤儿进程的成因和解决方法

孤儿进程: 一个父进程退出,而它的一个或者多个子进程还在运行,那么这些子进程就将成为孤儿进程。孤儿进程将被nit进程(进程号为1)所收养,并有init进程对他们状态收集工作。父进程先结束,释放了资源,然而子进程没人管了,由系统托管来释放资源,这就变成了孤儿进程。

僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或者waitpid获取子进程的状态信息,那么子进程的进程描述符等一系列信息还会保存在系统中。这种进程称之为僵死进程。子进程运行退出后,没有通知父进程回收子进程,子进程的资源没办法被父进程给释放,变成了死而占用资源的僵尸。
措施: 杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程。

//子进程变成了孤儿进程
#include <stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
    printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
    int p = fork();
    if ( p ==0  )
    {
        printf("I am child process\n");
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
        sleep(20);

    }else{
        printf("I am parent process \n");
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
//        exit(1);

    }

    printf("Hello world\n");
    return 0;
}

gcc fork.c
ps -elf |grep a.out 之后 父进程先退出了,变成了孤儿进程 子进程 被 1号进程接管,

//僵尸进程
#include <stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
    printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
    int p = fork();
    if ( p ==0  )
    {
        printf("I am child process\n");
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
        

    }else{
        printf("I am parent process \n");
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
        sleep(20);//子进程先结束掉,父进程没有收到信号, 子进程变成僵尸进程,等到父进程回收之后,子进程被init进程回收
//        exit(1);

    }

    printf("Hello world\n");
    return 0;
}

用wait() 系统调用来保证先去释放子进程再去释放父进程
int status;
pid_t p =wait(&status); 返回子进程的pid;
WIFEXITED(&status) 判断是否已经运行完毕了
WEXITSTATUS(status) 退出码

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

int main()
{
    printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
    int p = fork();
    if ( p ==0  )
    {
        printf("I am child process\n");
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
        
        sleep(30);

    }else{
        int status;
        printf("\nI am the parent process \n\n");
        pid_t p = wait(&status);
        
        printf("I am parent process pid = %d , child pid = %d  \n", getpid() , p);
        if( WIFEXITED(status) ) // WIFEXITED()  返回零时 正常退出,非零为,非正常退出
        {
            printf("EXIT code : %d\n", WEXITSTATUS(status));

        }else{
            printf("child crash\n");
        }
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
//        exit(1);

    }

    printf("Hello world\n");
    return 0;
}

wati() 与waitpid() 用法不同,功能一样
进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出。如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

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

int main()
{
    printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
    int p = fork();
    if ( p ==0  )
    {
        printf("I am child process\n");
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
        
        sleep(30);

    }else{
        int status;
        printf("\nI am the parent process \n\n");
        pid_t p = waitpid(pid , &status, 0);
        
        printf("I am parent process pid = %d , child pid = %d  \n", getpid() , p);
        if( WIFEXITED(status) ) // WIFEXITED()  返回零时 正常退出,非零为,非正常退出
        {
            printf("EXIT code : %d\n", WEXITSTATUS(status));

        }else{
            printf("child crash\n");
        }
        printf("getpid()= %d , getppid()= %d , getuid()= %d , geteuid()= %d\n",getpid(), getppid(),getuid(), geteuid());
//        exit(1);

    }

    printf("Hello world\n");
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值