PHP共享块内存和fork

发布于 2024-10-30 17:03:11 字数 1240 浏览 1 评论 0原文

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

    $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

我想创建此类以在多线程中读取和写入文件中的字符串。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦开始←不甜 2024-11-06 17:03:11

您根本不会结束子进程,它们永远不会完成。您也不会检查进程是否正确分叉,无法控制已完成的处理内容以及处理顺序。分叉一个进程并不是其他语言提供的真正的多线程,所发生的只是当前进程被复制并且变量被共享 - 你的 $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
        }
    }
}

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
        }
    }
}
陌路黄昏 2024-11-06 17:03:11

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

除非您试图创建本地化的分叉炸弹,否则您可能不希望您的分叉分叉。

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

完整的猜测。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文