PHP共享块内存和fork


PHP Shared block memory and fork

我试图创建计数器,使用共享块内存,只是看代码:

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

但是会得到奇怪的结果

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

我想创建这个类用于在多线程中读写文件中的字符串。

您根本没有结束子进程,它们永远不会完成。您也没有检查进程是否正确分叉,无法控制哪些进程以何种顺序完成了处理。fork进程并不是其他语言提供的多线程,所发生的一切都是当前进程被复制和变量被共享——你的$i不会在3结束,也没有保证哪个进程第一个或最后一个完成。

试一试:

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
        }
    }
}

您在调用pcntl_fork后不处理PID。您的分叉正在分叉,因为循环继续执行并分叉。

除非你想创建一个本地化的分叉炸弹,否则你可能不希望你的分叉分叉。

我在当地做了一些工作,试图弄清楚是否仅凭这一点就能解决问题,但没有。看起来好像没有正确地写入共享内存段,就好像字符串两边的一个数字被重复了,这会破坏所有的内存段,并迫使事情重新开始。

完整的猜测。

您可能需要考虑使用PHP执行并行处理的另一种方式。使用Gearman作为多进程工作队列是我最喜欢的解决方案。