【问题标题】:waiting for all pids to exit in php等待所有 pid 在 php 中退出
【发布时间】:2012-04-29 05:48:32
【问题描述】:

我的问题是这个。我正在分叉一个进程,以便我可以加快对磁盘上文件的访问时间。我将这些文件中的任何数据存储在本地桌面上的 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);      

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

【问题讨论】:

  • 您可以尝试循环遍历 $pids[$numChild]php.net/pcntl_waitpid(与 pcntl_wait 不同)中的每个 pid。
  • 所以我要在foreach() 循环之外进行测试吗?

标签: php fork


【解决方案1】:

尝试重组您的代码,使您有两个循环 - 一个产生进程,一个等待它们完成。您还应该使用 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

【讨论】:

  • 感谢您的更新。新的 fork 有很多东西要学。让我试一试,看看我在哪里。
  • @DaveRandom 使用这种方法,我们将无法限制生成的子节点的最大数量?
  • 好的,我知道了,我们可以在父节点中进行监控。
猜你喜欢
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多