首页后端开发PHP详解PHP的多进程操作实例,你都了解多少?

详解PHP的多进程操作实例,你都了解多少?

时间2024-03-26 00:50:03发布访客分类PHP浏览722
导读:这篇文章主要给大家分享一些PHP的多进程操作实例,下文实例代码及注释都很详细,具有一定的参考价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章能有所收获,接下来小编带着大家一起了解看看。 php的多进程处理依赖于pcntl扩展,通过pcn...

这篇文章主要给大家分享一些PHP的多进程操作实例,下文实例代码及注释都很详细,具有一定的参考价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章能有所收获,接下来小编带着大家一起了解看看。

php的多进程处理依赖于pcntl扩展,通过pcntl_fork创建子进程来进行并行处理。

例1如下:

?php
$pid = pcntl_fork();


if($pid == -1) {
    
  //错误处理:创建子进程失败时返回-1.
  die('fork error');

}
 else if ($pid) {
    
  //父进程会得到子进程号,所以这里是父进程执行的逻辑
  echo "parent \n";
    
  //等待子进程中断,防止子进程成为僵尸进程。
  pcntl_wait($status);

}
 else {
    
  //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
  echo "child \n";
    

  exit;

}
    

pcntl_fork创建了子进程,父进程和子进程都继续向下执行,而不同是父进程会获取子进程的$pid也就是$pid不为零。而子进程会获取$pid为零。通过if else语句判断$pid我们就可以在指定位置写上不同的逻辑代码。

上述代码会分别输出parent和child。那么输出的parent和child是否会有顺序之分?是父进程会先执行?

例2如下:

?php
$pid = pcntl_fork();


if($pid == -1) {
    
  die('fork error');

}
 else if ($pid) {
    
  sleep(3);
    
  echo "parent \n";
    
  pcntl_wait($status);

}
 else {
    
  echo "child \n";
    

  exit;

}
    

我们在父进程中通过sleep来延缓执行,看看效果。

结果是,很快输出了child,等待了接近3秒后,才输出parent。所以父进程和子进程的执行是相对独立的,没有先后之分。

那么问题又来了?pcntl_wait是做什么用的?
会挂起当前进程,直到子进程退出,如果子进程在调用此函数之前就已退出,此函数会立刻返回。子进程使用的资源将被释放。

例3如下:

?php
$pid = pcntl_fork();


if($pid == -1) {
    
  die('fork error');

}
 else if ($pid) {
    
  pcntl_wait ($status);
    
  echo "parent \n";

}
 else {
    
  sleep(3);
    
  echo "child \n";
    

  exit;

}
    

上述代码,我们可以看到,父进程执行pcntl_wait时就已经挂起,直到等待3秒后输出child,子进程退出后。父进程继续执行,输出parent。

例4如下:

?php
define('FORK_NUMS', 3);
    

$pids = array();
    

for($i = 0;
     $i  FORK_NUMS;
 ++$i) {
    
  $pids[$i] = pcntl_fork();

  if($pids[$i] == -1) {
    
    die('fork error');

  }
 else if ($pids[$i]) {
    
    pcntl_waitpid($pids[$i], $status);
    
    echo "pernet \n";

  }
 else {
    
    sleep(3);
    
    echo "child id:" . getmypid() . " \n";
    
    exit;

  }

}
    

上述代码,我们创建3个子进程,父进程分别挂起等待子进程结束后,输出parent。

输出结果如下:

child id:19090
pernet
child id:19091
pernet
child id:19092
pernet

例5如下:

?php
define('FORK_NUMS', 3);
    

$pids = array();
    

for($i = 0;
     $i  FORK_NUMS;
 ++$i) {
    
  $pids[$i] = pcntl_fork();

  if($pids[$i] == -1) {
    
    die('fork error');

  }
 else if ($pids[$i]) {


  }
 else {
    
    sleep(3);
    
    echo "child id:" . getmypid() . " \n";
    
    exit;

  }

}
    

foreach($pids as $k =>
 $v) {

  if($v) {
    
    pcntl_waitpid($v, $status);
    
    echo "parent \n";

  }

}
    

输出结果如下:

child id:19118
child id:19119
child id:19120
parent
parent
parent

为什么上述代码跟例4的输出结果不一样?

我们可以看到例5的pcntl_waitpid函数放在了foreach中,foreach代码是在主进程中,也就是父进程的代码中。当执行foreach时,可能子进程已经全部执行完毕并退出。pcntl_waitpid会立刻返回,连续输出三个parent。

(*在子进程中,需通过exit来退出,不然会产生递归多进程,父进程中不需要exit,不然会中断多进程。)

例6如下:

?php
define('FORK_NUMS', 3);
    

$pids = array();
    

$fp = fopen('./test.log', 'wb');
    
$num = 1;
    

for($i = 0;
     $i  FORK_NUMS;
 ++$i) {
    
  $pids[$i] = pcntl_fork();

  if($pids[$i] == -1) {
    
    die('fork error');

  }
 else if ($pids[$i]) {



  }
 else {
    
    for($i = 0;
     $i  5;
 ++$i) {
    

      flock($fp, LOCK_EX);

      fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {
$num}
     \r\n");
    

      flock($fp, LOCK_UN);
    
      echo getmypid(), ": success \r\n";
    
      ++$num;

    }
    
    exit;

  }

}
    

foreach($pids as $k =>
 $v) {

  if($v) {
    
    pcntl_waitpid($v, $status);

  }

}
    

fclose($fp);
    

代码如上:我们创建三个子进程,来同时向test.log文件写入内容,test.log内容如下:

19507 : 2016-03-16 20:40:52 : 1
19507 : 2016-03-16 20:40:52 : 2
19507 : 2016-03-16 20:40:52 : 3
19507 : 2016-03-16 20:40:52 : 4
19507 : 2016-03-16 20:40:52 : 5
19509 : 2016-03-16 20:40:52 : 1
19509 : 2016-03-16 20:40:52 : 2
19509 : 2016-03-16 20:40:52 : 3
19509 : 2016-03-16 20:40:52 : 4
19509 : 2016-03-16 20:40:52 : 5
19508 : 2016-03-16 20:40:52 : 1
19508 : 2016-03-16 20:40:52 : 2
19508 : 2016-03-16 20:40:52 : 3
19508 : 2016-03-16 20:40:52 : 4
19508 : 2016-03-16 20:40:52 : 5

我们可以看到三个子进程的pid,它们分别执行了5次,时间几乎是在同时。但是$num的值并没像我们期望的那样从1-15进行递增。子进程中的变量是各自独立的,互不影响。子进程会自动复制父进程空间里的变量。

如何在进程中共享数据?

我们通过php的共享内存函数shmop来实现。

?php
define('FORK_NUMS', 3);
    

$pids = array();
    

$fp = fopen('./test.log', 'wb');
    
$num = 1;
    
//共享内存段的key
$shmKey = 123;
    
//创建共享内存段
$shmId = shmop_open($shmKey, 'c', 0777, 64);
    
//写入数据到共享内存段
shmop_write($shmId, $num, 0);
    

for($i = 0;
     $i  FORK_NUMS;
 ++$i) {
    
  $pids[$i] = pcntl_fork();

  if($pids[$i] == -1) {
    
    die('fork error');

  }
 else if ($pids[$i]) {
    

    //阻塞,等待子进程退出

    //注意这里,如果是非阻塞的话,$num的计数会出现问题。
    pcntl_waitpid($pids[$i], $status);

  }
 else {
    
    //读取共享内存段中的数据
    $num = shmop_read($shmId, 0, 64);
    
    for($i = 0;
     $i  5;
 ++$i) {

      fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {
$num}
     \r\n");
    
      echo getmypid(), ": success \r\n";
    
      //递增$num
      $num = intval($num) + 1;

    }
    

    //写入到共享内存段中

    shmop_write($shmId, $num, 0);
    
    exit;

  }

}
    

//shmop_delete不会实际删除该内存段,它将该内存段标记为删除。
shmop_delete($shmId);
    
shmop_close($shmId);
    
fclose($fp);
    

上述代码的运行结果如下:

19923 : 2016-03-17 00:05:18 : 1
19923 : 2016-03-17 00:05:18 : 2
19923 : 2016-03-17 00:05:18 : 3
19923 : 2016-03-17 00:05:18 : 4
19923 : 2016-03-17 00:05:18 : 5
19924 : 2016-03-17 00:05:18 : 6
19924 : 2016-03-17 00:05:18 : 7
19924 : 2016-03-17 00:05:18 : 8
19924 : 2016-03-17 00:05:18 : 9
19924 : 2016-03-17 00:05:18 : 10
19925 : 2016-03-17 00:05:18 : 11
19925 : 2016-03-17 00:05:18 : 12
19925 : 2016-03-17 00:05:18 : 13
19925 : 2016-03-17 00:05:18 : 14
19925 : 2016-03-17 00:05:18 : 15

这样我们就在进程间共享了$num的数据。

关于PHP的多进程操作实例就介绍到这,上述实例代码具有一定的参考价值,对大家学习和理解PHP多进程都有一定的帮助,有需要的朋友可以参考,最后,想要了解更多PHP多进程的内容,大家可以关注其它的相关文章。

文本转载自脚本之家

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: 详解PHP的多进程操作实例,你都了解多少?
本文地址: https://pptw.com/jishu/653150.html
css初始化是什么,为何要初始化CSS 用PHP怎样做账号不能同时登陆的功能?

游客 回复需填写必要信息