PHP Shared block memory and fork

2019-08-25 00:59发布

问题:

Im trying to create counter that using shared block memory, just look code:

    $i=0; $counter = new counter('g');
while($i<3){
  $pid = pcntl_fork();
  echo $counter->get()."\t".$i."\t".$pid."\n";
  $i++;
}

class counter {
  protected static $projID = array();
  protected $t_key;
  protected $length;

  function __construct($projID){
    !in_array( $projID, self::$projID) or die('Using duplicate project identifer "'.$projID.'" for creating counter');
    self::$projID[] = $projID;
    $this->t_key = ftok(__FILE__, $projID);
    $this->shmid = shmop_open($t_key, 'c', 0755, 64);
    $this->length = shmop_write($this->shmid, 0, 0);
    shmop_close($this->shmid);
  }

  function get(){
    $sem = sem_get($this->t_key, 1);
    sem_acquire($sem);
      $shmid = shmop_open($this->t_key, 'c', 0755, 64);
      $inc = shmop_read($shmid, 0, $this->length);
      $this->length = shmop_write($shmid, $inc+1, 0);
      shmop_close($shmid);
    sem_release($sem);
    return $inc;
  }
}

But il get strange result

7   0   2567
8   1   2568
9   0   0
1   1   0
2   2   2569
40  1   2570
4   2   2572
3   2   0
51  2   2571
52  1   0
63  2   0
5   2   0
64  2   2573
65  2   0

I want to create this class for read and write strings in file in multithreading.

回答1:

You're not ending child processes at all, they'll never finish. You're also not checking whether the process forked correctly or not, there's no control over what's finished processing and in what order. Forking a process isn't really multithreading that other languages provide, all that happens is that the current process is being copied and variables are shared - your $i won't end at 3, nor is there a guarantee which process is finishing first or last.

Try with:

while($i < 3)
{
    $pid = pcntl_fork();

    if($pid == -1)
    {
        // some sort of message that the process wasn't forked 
        exit(1);
    }
    else
    {
        if($pid)
        {
            pcntl_wait($status); // refer to PHP manual to check what this function does
        }
        else
        {
            // enter your code here, for whatever you want to be done in parallel
            // bear in mind that some processes can finish sooner, some can finish later
            // good use is when you have tasks dependent on network latency and you want
            // them executed asynchronously (such as uploading multiple files to an ftp or 
            // synchronizing of something that's being done over network

            // after you're done, kill the process so it doesn't become a zombie

            posix_kill(getmypid(), 9); // not the most elegant solution, and can fail
        }
    }
}


回答2:

You aren't dealing with the PID after your call to pcntl_fork. Your forks are forking because the loop continues to execute and fork.

Unless you're trying to create a localized fork bomb, you probably don't want your forks to fork.

I did some work locally to try and figure out if that alone would solve the problem, but it didn't. It almost looks like the shared memory segment isn't being written to correctly, as if one of the digits on either side of the string is being repeated, which corrupts all of it and forces things to start over.

Complete speculation.

You might want to consider a different way of performing parallel processing with PHP. Using Gearman as a multi-process work queue is a favorite solution of mine.