2011-02-17 97 views
0

我有以下的测试PHP做一个叉/产卵过程,其中测试还企图杀死子进程(僵尸)之后完成..PHP分叉问题

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

运行时,我遇到了一个内存分配错误,并且有太多的进程在它们被移除之前被派生。

任何指针将这个感谢的是极大的赞赏..

$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"; 
} 

更新::: 设法得到什么,我认为这是一个解决方案.....

//--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; 
      } 
    } 

回答

2

只需使用pcntl_wait()。没有必要查看子进程是否完成,只需调用pcntl_wait()并阻塞,直到获得子进程。

避免传递WNOHANG,以便您的父进程将坐下并等待孩子完成。

$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); 
1

叉子的foreach:

<? 
declare(ticks=1); 
pcntl_signal(SIGUSR1, create_function('$signo', 'sleep(1);while (($pid=pcntl_wait(@$status, WNOHANG))>0) {}'));//protect against zombie children 
foreach ($tasks as $v) 
     {if (($pid=pcntl_fork())===-1) 
      {//... 
      continue; 
      } 
     else if ($pid===0) 
       {ob_start();//prevent output to main process 
       register_shutdown_function(create_function('$pars', 'ob_end_clean();posix_kill(posix_getppid(), SIGUSR1);posix_kill(getmypid(), SIGKILL);'), array());//to kill self before exit();, or else the resource shared with parent will be closed 
       //... 
       exit();//avoid foreach loop in child process 
       } 
     } 
?> 
本;

,可随时更换你写的代码收获(你的例子中,从第58行 '$ Q =真')