2012-04-17 54 views
3

我的问题是这样的。我正在分流一个进程,以便加速磁盘上文件的访问时间。我将来自这些文件的任何数据存储在本地台上的tmp文件中。理想情况下,在所有进程完成后,我需要访问该tmp文件并将数据存入数组。然后我断开tmp文件的链接,因为它不再需要。我的问题是,看起来似乎pcntl_wait()并没有等到所有子进程完成之后才进入最后一组操作。所以我最终在一些随机过程完成前断开该文件。等待所有的pid退出php

我似乎无法找到一个稳定的方式来等待所有进程干净地退出然后访问我的数据。

$numChild  = 0;  
    $maxChild  = 20; // max number of forked processes. 

    // get a list of "availableCabs" 

    foreach ($availableCabs as $cab) { 

      // fork the process 
      $pids[$numChild] = pcntl_fork(); 

      if (!$pids[$numChild]) { 

        // do some work  
        exit(0); 

      } else { 

        $numChild++; 
        if ($numChild == $maxChild) { 

          pcntl_wait($status); 
          $numChild--; 

        } 

      } // end fork 

    } 

    // Below is where things fall apart. I need to be able to print the complete serialized data. but several child processes don't actually exit before i unlink the file. 

    $dataFile = fopen($pid, 'r'); 

    while(($values = fgetcsv($dataFile,',')) !== FALSE) { 
      $fvalues[] = $values; 
    } 

    print serialize($fvalues); 

    fclose($dataFile); 
    unlink($file);  

请注意,我留下了很多关于我在做什么的代码,如果我们需要发布那些问题。

+1

你可以尝试通过每一个PID循环在'$的PID [$ numChild]'和http://php.net/pcntl_waitpid(这是从pcntl_wait不同)每个。 – 2012-04-17 20:47:32

+0

所以我在'foreach()'循环之外测试? – 2012-04-17 20:49:35

回答

5

尝试重构您的代码,以便您有两个循环 - 一个生成进程和一个等待它们完成的循环。您还应该使用pcntl_waitpid()来检查特定的进程ID,而不是您正在使用的简单子计数方法。

事情是这样的:

<?php 

    $maxChildren = 20; // Max number of forked processes 
    $pids = array();  // Child process tracking array 

    // Get a list of "availableCabs" 

    foreach ($availableCabs as $cab) { 

    // Limit the number of child processes 
    // If $maxChildren or more processes exist, wait until one exits 
    if (count($pids) >= $maxChildren) { 
     $pid = pcntl_waitpid(-1, $status); 
     unset($pids[$pid]); // Remove PID that exited from the list 
    } 

    // Fork the process 
    $pid = pcntl_fork(); 

    if ($pid) { // Parent 

     if ($pid < 0) { 
     // Unable to fork process, handle error here 
     continue; 
     } else { 
     // Add child PID to tracker array 
     // Use PID as key for easy use of unset() 
     $pids[$pid] = $pid; 
     } 

    } else { // Child 

     // If you aren't doing this already, consider using include() here - it 
     // will keep the code in the parent script more readable and separate 
     // the logic for the parent and children 

     exit(0); 

    } 

    } 

    // Now wait for the child processes to exit. This approach may seem overly 
    // simple, but because of the way it works it will have the effect of 
    // waiting until the last process exits and pretty much no longer 
    foreach ($pids as $pid) { 
    pcntl_waitpid($pid, $status); 
    unset($pids[$pid]); 
    } 

    // Now the parent process can do it's cleanup of the results 
+0

感谢您的更新。新分叉这么多学习。让我试试看看我在哪里。 – 2012-04-18 11:23:11

+0

运作良好。谢谢您的帮助。 – 2012-04-18 12:57:17

+0

不用担心。 :-) – DaveRandom 2012-04-18 12:58:33