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

2つのループができるようにコードを再構築してみてください。1つはプロセスを生成し、もう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
于 2012-04-17T21:16:34.380 に答える