2011-02-17 96 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 =真')