码迷,mamicode.com
首页 > 其他好文 > 详细

关于如何有效避免僵尸进程的一种探索。(动手写自己的http服务器)

时间:2014-05-13 17:17:18      阅读:339      评论:0      收藏:0      [点我收藏+]

标签:style   blog   class   code   java   c   

关于如何避免僵尸进程。其实方法很多。有很多现成的解决方案。这里给出一个简单的方案。以及背后思考的过程。

设想一种最简单的http服务器:

伪代码:

当接收到一个tcp请求的时候.

fork 一个子进程去做工作。

主进程依旧在监听下面要来的请求。

 

这个模型实际上会导致。因为fork出来的子进程没有回收,并且父进程一直存在没有结束。导致越来越多的僵尸进程出现。

都知道子进程结束的时候会发一个sigchld信号给父进程。于是改进成增加一行代码:

signal(SIGCHLD,deal_signal);

void deal_signal()

  wait(NULL);

}

但是这样做。依旧会有大量的僵尸进程存在。因为如果sigchid信号不断的发往 主进程。主进程是不会维护一个队列去缓存这些信号的。

而是 直接把这些信号全部丢弃掉。从而导致我们无法避免僵尸进程的存在。

百度一下 发现很多答案都是要这么写

void deal_signal()

  while(waitpid(-1,NULL,WNOHANG)>0);

}

经过测试 这样写可以避免僵尸进程.因为这里 的waitpid在一个循环内。也就是说 如果有信号被丢弃。但是因为信号被丢弃 但是进程还在。

所以这个循环会一直去寻找子进程 一直到所有子进程全部被回收为止。

 

但是问题就出在这。

既然上面的解决方案的key是因为while。哪我们能不能写成while(wait(NULL)>0)来避免僵尸进程呢。

为了证明这个问题。我们写代码来测试一下。

 

bubuko.com,布布扣
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>



int main(int argc, char const *argv[])
{
    int i;

    pid_t pc;


        void deal_signal();
    signal(SIGCHLD,deal_signal);

    for (i = 0; i < 100; ++i)
    {

         pc=fork();

        switch(pc)
        {
            case 0:
            printf(" child process is %d\n", getpid());
            break;

            default:
            printf(" father proces is %d\n",getpid() );
            continue;
        }
                //用来保证所有的子进程直接退出 而不是继续循环
        if(pc==0)
            break;
        
    }
    
        //这里保证 如果是父进程那么就一直阻塞。
       //因为你如果不阻塞这个父进程 在shell里面跑这个程序 会立即执行完毕
      //那么主进程就结束了 所以你永远也check不到有僵尸进程的存在
     //因为当主进程结束的时候 那些子进程的父进程就变成了init进程
    if (pc>0)
    {
        while(1)
        {

        }
    }

    return 0;
}

bubuko.com,布布扣

 

在终端1 上面运行这个程序

 

然后在终端2 上面 输入命令

ps -A -ostat,ppid,pid | grep -e ‘^[Zz]‘

你会发现 可以看到 我们代码生成出来的那些僵尸进程了。

 

于是我们更改代码:

bubuko.com,布布扣
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

int number=0;

int main(int argc, char const *argv[])
{
    int i;

    pid_t pc;


    void deal_signal();
    signal(SIGCHLD,deal_signal);

    for (i = 0; i < 100; ++i)
    {

         pc=fork();

        switch(pc)
        {
            case 0:
            printf(" child process is %d\n", getpid());
            break;

            default:
            printf(" father proces is %d\n",getpid() );
            continue;
        }
        if(pc==0)
            break;
        
    }
    
    if (pc>0)
    {
        while(1)
        {

        }
    }

    return 0;
}

void deal_signal()
{
    while(wait(NULL)>0)
    {
       number++;
       printf("%d\n", number);

    }

        
}
bubuko.com,布布扣

这个时候 我们再运行一次程序。并且在另外一个终端上面 运行命令

 

就会发现 是找不到僵尸进程的。

 

so 实际上 while(wait(NULL)>0)

这种写法 不但有效 而且更加简单方便理解。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

关于如何有效避免僵尸进程的一种探索。(动手写自己的http服务器),布布扣,bubuko.com

关于如何有效避免僵尸进程的一种探索。(动手写自己的http服务器)

标签:style   blog   class   code   java   c   

原文地址:http://www.cnblogs.com/punkisnotdead/p/3724554.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!