僵尸进程

1、创建一个僵尸进程

一个例子:

僵尸进程:

 

 

源程序:

 

/*

 * zombie.c

 * version 1

 * Created on: 2013-11-23

 * Author: Zhenghua Xue

 */

#include <stdio.h>

#include <sys/ptrace.h>

#include <sys/user.h>

#include <sys/wait.h>

#include <sys/types.h>

#include <unistd.h>

#include <stdlib.h>

#include <signal.h>

#include <assert.h>

#include <sys/time.h>

 

 

int main (){

  intcount = 1;

   printf("%dth Spawning;\n",++count);

   createChild(count);

return 0;

}

 

 

int createChild(int count)

{

       pid_t fpid; //fpid表示fork函数返回的值

       //int count = 1;

       int status = 0;

       int duration = 20;

 

         fpid=fork();

         if (fpid < 0)

                printf("error infork!");

         else if (fpid == 0) {

                printf("%dst Child PID:%d;\n",count,getpid());

                struct timeval start;

                struct timeval end;

                gettimeofday(&start, NULL);

                int t = 0;

                while(1){

                   t++;

                   t--;

                   gettimeofday(&end,NULL);

                   if( (end.tv_sec-start.tv_sec)> duration ) {

                      printf("child %dexit\n",getpid());

                      break;

                   }

                   //sleep(2);

                }

                exit(0);//如果不加这行,函数退不出去,大量child sleep后面的PID都变得不固定了

         }

         else {

                printf("%dst ParentPID:  %d\n",count,getpid());

                                //waitpid(-1,&status,WNOHANG);//ifmul waitpid is running when called by main

                //不调用waitpid可能会产生僵尸进程

                while(1){

                       sleep(3);

                }

         }

       return 0;

}

2、分析僵尸进程

1)查找僵尸进程

[root@compute-20 oxuezh]# ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'
Zl       1   618 [libvirtd] <defunct>
Zl       1  1362 [libvirtd] <defunct>
Zl       1  3039 [libvirtd] <defunct>
Zl       1 12679 [libvirtd] <defunct>
Zl       1 15190 [libvirtd] <defunct>


2)僵尸进程产生的原因:

 

1)程序运行一段时间,子进程退出,父进程还活着,但父进程未调用waitpidwait函数,产生了僵尸进程:

2)子进程没有使用exit函数,父进程还活着,即使父进程调用了waitpidwait函数,依然是僵尸进程。

 

此时如果杀掉父进程,子进程也就被连带杀掉了:

 

 

如果父进程退出后,子进程还在运行,此时,init会立刻接管子进程:如下图所示。

父进程9365退出后:

 

3)防止产生僵尸进程的方法

1)用wait,waitpid之类的函数获得进程的终止状态,以释放资源。子进程别忘了写exit。如果你能保障你的父进程一定会先于子进程退出,你也可以不用waitwaitpid,子进程结束后,会被过继给init进程,它会回收子进程。

2waitpid函数是阻塞函数,父进程有可能还需要做其他事情,不愿意阻塞在那。这种情况下,fork两次,其实质还是把孙子进程过继给了init进程,以达到立刻回收目的。可以解决。当然,waitpid函数中加上WNOHANG也可以使得父进程不阻塞,而继续干自己的事。儿子进程产生孙子进程后,马上退出。孙子进程结束后,由于儿子进程已经结束,故会被1号进程init接管,init会释放它。父进程可以干自己想干的事。


3、诡异的僵尸进程

1)父进程为init进程,但就是不收尸


[root@compute-20 oxuezh]# ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'
Zl       1   618 [libvirtd] <defunct>
Zl       1  1362 [libvirtd] <defunct>
Zl       1  3039 [libvirtd] <defunct>
Zl       1 12679 [libvirtd] <defunct>
Zl       1 15190 [libvirtd] <defunct>
 


还未解决,好像除了杀父进程没有更好的办法,但父进程偏偏是1号进程,无法杀。写了一个内核程序,通过改变进程状态试图回收,没有生效,程序可能有问题,继续研究。。。。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值