您的位置:首页 >  新闻中心 > 行业动态
  行业动态
 

PHP多进程编程之僵尸进程问题

来源:原创    时间:2017-10-17    浏览:0 次

 经过运用pcntl_fork函数,我们现已有了新的子进程,而子进程接下来完结我们需求处理的内容,那么我们就暂时叫做service()吧,而且我们需求很多个service()进行处理,再次参照我们之前的需求,父进程需求一向循环读取配置文件,等候文件发作改动。经过对pcntl_fork的办法,很简单我们就能够写出如下代码:


$res = config();//kill进程

for($i = 0; $i < $res[sum]; $i++) {    
       $pid = pcntl_fork();    
        if ($pid == 0) {
         service();        
         return;
       }
}

代码中注释的当地我们需求在配置文件中发作改动的时分杀死进程,杀死进程的的办法很简单,能够运用kill指令直接杀死,比方(假定pid为123):

1 kill 123
可是我们发现,运用这个杀死进程的办法并没有真实的把进程杀死,这个子进程被杀身后还占用这个进程的资源,我们成为僵尸进程,僵尸进程是运用kill指令无法杀死的。想要处理这个问题,我们能做的只要两种办法。

1. shutdown

2. 杀死该进程的父进程。

可是这两种办法都不可,由于这个程序的意图是监控常驻在服务器内,服务器不能封闭,而且父进程也不能被干掉。这时分我们看到了官方文档关于fork办法的解说:

1 pcntl_wait($status); //等候子进程中止,避免子进程成为僵尸进程。
本来有种办法能够避免进程成为僵尸进程,可是,官网给出的代码是这姿态的:


 1 $pid = pcntl_fork(); 
 2 //父进程和子进程都会履行下面代码 
 3 if ($pid == -1) { 
 4     //错误处理:创立子进程失利时回来-1. 
 5      die('could not fork'); 
 6 } else if ($pid) { 
 7      //父进程会得到子进程号,所以这儿是父进程履行的逻辑 
 8      pcntl_wait($status); //等候子进程中止,避免子进程成为僵尸进程。 
 9 } else {
10      //子进程得到的$pid为0, 所以这儿是子进程履行的逻辑。
11 }

什么意思呢?就是父进程会等候子进程运转,等子进程运转完毕之后,才会进行下一步,而且也会消除僵尸进程。可是这儿又和我们的需求不符合了,我们的子进程为一个死循环的程序,不断的查找输出,更本没有完毕的时分,而且我们需求的是异步处理而不是同步。可是这个办法能够用吗?其实当然能够。

在pcntl_wait的文档中是这么解说这个函数的:

wait函数刮起当时进程的履行直到一个子进程退出或接收到一个信号要求中止当时进程或调用一个信号处理函数。 如果一个子进程在调用此函数时现已退出(俗称僵尸进程),此函数马上回来。子进程运用的一切体系资源将 被开释。关于wait在您体系上作业的具体标准请查看您体系的wait(2)手册。

我们发现,当这个函数发现子进程成为了僵尸进程就会开释僵尸进程的资源——条件是这个僵尸进程为这个父进程的子进程。那么我们就能够奇妙的运用这个办法让这些僵尸进程开释资源了,所以就有了如下代码:

1 posix_kill(123, 9);
2 pcntl_wait($status);
这样我们先运用kill干掉这个进程,这个进程就不会再运转了,可是这个进程成为了僵尸进程,占用着资源,我们下一句就履行一次pcntl_wait()让这些僵尸进程开释资源,这样,子进程才真实的被停止了,僵尸进程被消除了。