本文介绍了PHP的分叉问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下测试php来执行fork/spawn进程,该测试还尝试在完成后杀死子进程(僵尸)..

I have the following test php to do a fork/spawn process, where the test also attempts to kill the child process (zombie) after is completes..

我想拥有一个更高效的流程,在该流程中,所有子流程都应尽快从流程表中立即删除.当前尝试填满了进程表,并导致内存分配问题,从而关闭了系统.该应用程序在Fedora/Centos系统上运行.

I'd like to have a more efficient process, where any child processes are immediately removed from the process table as soon as possible. The current attempt fills up the process table, and causes a memory allocation issue that shuts down the system. The app is running on a Fedora/Centos system.

运行此程序时,我遇到了内存分配错误,并且在删除它们之前产生了太多的进程.

I'm running into a memory allocation err when this runs, and there are too many processes that get spawned, before they get removed.

感谢任何指针.

$fname="ef_deptData.txt";

$t=0;
$pids = array();
$pids1[] = array();


$fh=fopen($fname,"r");
$p=0;
while(!feof($fh))
{
    print " inside course   pppppppppppppppppppppp \n";
    //--go ahead and parse the line of input from the file
    //--(if it exists)

    $buf = fgets($fh);

    $buf=trim($buf);
    if($buf)
    {
        $data1=explode("&&",$buf);
        $stateVal=trim($data1[0]);
        $collegeVal=trim($data1[1]);
        $campusVal=trim($data1[2]);

        $pid = pcntl_fork();

        //process the spawned child procs
        if($pid)
        {
            $pids[$p]=$pid;
            $p=$p+1;
        }
        else
        {
            $app="ef_course.py";

            $args[0]='"'.$stateVal.'"';
            $args[1]='"'.$collegeVal.'"';
            $args[2]='"'.$campusVal.'"';

            pcntl_exec($app, $args);
        }
    }
    $t=$t+1;
    if($t==40)
    {
        sleep(5);
        $t=0;
    }
}


    // --this section is a kludge to see if the child process is complete
    // --prior to deleting the spwaned child process (should be a better way)
$q=true;
    while($q)
    {
            $a="ps -aux  |  grep ef_course   | grep -v grep   |   awk '{print $8}'";
            $a=`$a`;
            $t=explode("\n",$a);
            $t=array_slice($t,1,-1);
            print_r($t);
            sleep(5);
            $y=0;

            for($i=0;$i<count($t);$i++)
            {
                    if((strcmp($t[$i],"Z+")!=0)&&(strcmp($t[$i],"Z")!=0))
                    {
                            $y=1;
                            print "ddd \n";
                    }
           }

           if($y==0)
    {
        //--try to go ahead and kill the zombie processes
        $w="pgrep ef_course";
        $r=`$w`;
        if($r!="")
        {
            //foreach($pids as $p){ posix_kill($p,SIGHUP); }
            //foreach($pids as $p){ posix_kill($p,SIGINT); }
            foreach($pids as $p){ posix_kill($p,SIGTERM); }

            $dead_and_gone = pcntl_waitpid(-1,$status,WNOHANG);
            while($dead_and_gone > 0){
                // Remove the gone pid from the array
                unset($pids[array_search($dead_and_gone,$pids)]);

                // Look for another one
                $dead_and_gone = pcntl_waitpid(-1,$status,WNOHANG);
            }
            print_r($pids);
        }
        else
            $q=false;
    }
    sleep(10);
    print "waiting for ef_course.py to complete \n";
}

更新:::设法得到了我认为的解决方案.....

update:::managed to get what i think is a solution.....

 //--start the process to get the store urls..
 $fname="ef_programData.txt";

 $t=0;
 $pids = array();
 $pids1[] = array();


  $fh=fopen($fname,"r");
  $p=0;
  while(!feof($fh))
  {
          print " inside program   pppppppppppppppppppppp \n";
         //--go ahead and parse the line of input from the file
         //--(if it exists)

            $tmp=array();
            $buf = fgets($fh);

            $buf=trim($buf);
            if($buf)
            {
                   $data1=explode("&&",$buf);

                   $pid = pcntl_fork();

                   //process the spawned child procs
                   if($pid)
                   {
                          $pids[]=$pid;
                   }
                    else
                     {
                           $args=array();
                           $app="foo.py";

                           $args[0]='"'.$stateVal.'"';

                           pcntl_exec($app, $args);
                    }

                    while(pcntl_wait($status, WNOHANG) > 0) {
                      usleep(500);
                    }

                     while(list($key, $val) = each($pids)) {
                     if(!posix_kill($val, 0)) { // This detects if the child is still running or not
                           unset($pids[$key]);
                     }
                    }
                    $pids = array_values($pids); // Reindex the array

            }
            $t=$t+1;
            if($t==40)
            {
                    sleep(5);
                    $t=0;
            }
    }

推荐答案

只需使用pcntl_wait().无需查看子进程是否已完成,只需调用pcntl_wait()并阻塞直到获得子进程即可.

Just use pcntl_wait(). There's no need to see if the child process has finished, just call pcntl_wait() and block until the child is reaped.

避免传递WNOHANG,这样您的父进程将坐下来等待孩子完成.

Avoid passing WNOHANG so that your parent process will sit and wait for a child to finish.

您可以使用以下代码替换您编写的收割代码(从示例的第58行'$ q = true;'开始):

You can replace the reaping code you've written (starting at line 58 '$q=true;' of your example) with this:

$status = null;

do {
    // You can use $status with pcntl_wifexited(), pcntl_wifstopped(),
    // pcntl_wifsignaled(), pcntl_wexitstatus(), pcntl_wtermsig() and
    // pcntl_wstopsig() if you need to.

    $pid = pcntl_wait($status);

} while ($pid > 0);

这篇关于PHP的分叉问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 06:07