7

我的问题是这个。我正在分叉一个进程,以便我可以加快对磁盘上文件的访问时间。我将这些文件中的任何数据存储在本地桌面上的 tmp 文件中。理想情况下,在所有进程完成后,我需要访问该 tmp 文件并将该数据放入一个数组中。然后我取消链接 tmp 文件,因为它不再需要。我的问题是 pcntl_wait() 似乎并没有真正等到所有子进程都完成后再继续进行最后一组操作。所以我最终在一些随机过程完成之前取消了该文件的链接。

我似乎找不到一种可靠的方法来等待所有进程干净地退出然后访问我的数据。

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

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

4

1 回答 1

13

尝试重组你的代码,让你有两个循环——一个产生进程,一个等待它们完成。您还应该使用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
于 2012-04-17T21:16:34.380 回答