关于如何避免僵尸进程。其实方法很多。有很多现成的解决方案。这里给出一个简单的方案。以及背后思考的过程。
设想一种最简单的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)来避免僵尸进程呢。
为了证明这个问题。我们写代码来测试一下。
#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;
}
在终端1 上面运行这个程序
然后在终端2 上面 输入命令
ps -A -ostat,ppid,pid | grep -e ‘^[Zz]‘
你会发现 可以看到 我们代码生成出来的那些僵尸进程了。
于是我们更改代码:
#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);}
}
这个时候 我们再运行一次程序。并且在另外一个终端上面 运行命令
就会发现 是找不到僵尸进程的。
so 实际上 while(wait(NULL)>0)
这种写法 不但有效 而且更加简单方便理解。
关于如何有效避免僵尸进程的一种探索。(动手写自己的http服务器)