PHP多进程之pcntl_fork的实例详解


Posted in PHP onOctober 15, 2017

PHP多进程编之pcntl_fork的实例详解

其实PHP是支持并发的,只是平时很少使用而已。平时使用最多的应该是使用PHP-FMP调度php进程了吧。

但是,PHP的使用并不局限于做Web,我们完全也可以使用PHP来进行系统工具类的编程,做监控或者是运维。在使用这些方向的时候,我们可以使用到PHP的更多特性,例如并发(多进程)、socket编程等。

那么接下来就说说我遇到的PHP多进程的编程。这个多进程的使用是有一个背景的,下面模糊描述一下背景。

我需要一个监控系统,当然使用PHP语言,监控系统需要监控很多种系统指标,为了让每个监控指标之间尽量专心的去做自己的事情,就需要单独使用一个进程去监控一个指标,还有一个进程去读取配置,拿到配置之后,根据配置去启动每条进程。

那么,这就需要我所说的多进程了。

  1. 首先启动一个主进程,主进程用来读取配置信息。例如,我读取到了我需要监控5个指标
  2. 接下来主进程启动5个子进程,分别监控这5个指标。
  3. 创建好5个指标监控进程之后之后,主进程进行监听配置。
  4. 一旦配置发生改变,杀死之前的进程并重新创建进程。

相对来说比较清晰的逻辑。那么接下来我们就化简一下操作:简单的说就是一个主进程创建5个子进程。

首先,创建进程在需要使用php的一个函数pcntl_fork(),这个函数可能有的同学不太熟,不过接触过Linux C变成的人都知道Linux下有个叫fork()的函数,用来创建子进程。这个函数和Linux下这个函数是一个意思。需要注意的是,这个函数在Linux下才能使用,而且需要安装pcntl的扩展。

对于这个函数怎么使用,我们可以查阅官方文档:http://php.net/manual/zh/function.pcntl-fork.php

官方文档是这样说的:

pcntl_fork()函数创建一个子进程,这个子进程仅PID(进程号) 和PPID(父进程号)与其父进程不同。fork怎样在您的系统工作的详细信息请查阅您的系统 的fork(2)手册。

成功时,在父进程执行线程内返回产生的子进程的PID,在子进程执行线程内返回0。失败时,在 父进程上下文返回-1,不会创建子进程,并且会引发一个PHP错误。

这样就可以创建一个子进程了,子进程创建成功以后会执行pcntl_fork()之后的方法。那么对于这个函数的返回值我们如何理解呢?

是这样的,我们调用函数创建进程的时候,函数执行时有时间的,而新的进程刚好是在函数执行开始和结束之间创建出来的,这样,新的进程也执行了这个函数,所以函数也需要有返回值。那么对于该函数一次执行之后,父进程和子进程都会受到该函数的返回值,由于父进程创建了子进程,而子进程并没有创建新的进程,所以子进程对于这个函数的返回结果是没有的,所以就给他赋了一个0。而父进程创建了子进程,子进程是存在pid的,所以就得到了那个进程的pid。

我们可以写个程序了解一下:

$pid = pcntl_fork();
var_dump($pid);

这个调用会输出两个值,但是我们如果直接print的只能看到一个值,也就是子进程的pid,但是使用var_dump我们就可以看到两个值,是0和子进程的pid。0这个值就是子进程返回过来的。

那么如何创建进程了解清楚之后,就可以开始创建进程了,我们需要创建5个进程,那么我就循环5次创建进程。得到如下代码:

$i=0;
 while($i!=5){
  $pid = pcntl_fork();
  echo $pid."---------hahah".$i++.PHP_EOL;
 }

这样就写好了,那么运行一下吧。啊?发现不是5个进程啊,发现有好多个进程,而且最后一个hahah4这个输出有32个,为什么是32呢?我们算一算。2^5=32,为什么最后的线程数以指数增长了呢?

想发现这个并不难,因为我们之后的每一条都执行了while循环,到最后成了进程的指数增长——也就是说fork的时候把while循环也带了进去。但是我们只是要5个进程而已。怎么办呢?

通过之前对函数的研究可以看到,子进程中会返回一个为0的值,那么我们就可以知道,0为子进程的标记。我们可以通过对子进程标记来结束进程执行。所以我们可以将我们的代码修改为如下形式:

$i=0;
while($i!=5){
 $pid = pcntl_fork();
 echo $pid."---------hahah".$i++.PHP_EOL;
 if ($pid == 0) {
  echo "子进程".PHP_EOL;
  return;
 }
}

因为0其实是对子进程的标记,那么pid这个变量在子进程里实际上是0的,所以当发现pid的值为0的时候,我们就可以断定我们当前进程为一个子进程,不需要在让他执行while并创建子进程的子进程了,所以在执行完我们的内容之后就return或者exit退出这个执行就好了。这样就能保证我们执行创建了5个进程而不是32个了。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

PHP 相关文章推荐
Smarty+QUICKFORM小小演示
Feb 25 PHP
PHP截取汉字乱码问题解决方法mb_substr函数的应用
Mar 30 PHP
Smarty模板学习笔记之Smarty简介
May 20 PHP
php采用curl实现伪造IP来源的方法
Nov 21 PHP
php实现每天自动变换随机问候语的方法
May 12 PHP
PHP7.0安装笔记整理
Aug 28 PHP
Zend Framework教程之Zend_Registry对象用法分析
Mar 22 PHP
PHP微信开发之文本自动回复
Jun 23 PHP
PHP编程中的Session阻塞问题与解决方法分析
Aug 07 PHP
PHP让数组中有相同值的组成新的数组实例
Dec 31 PHP
微信公众平台开发教程④ ThinkPHP框架下微信支付功能图文详解
Apr 10 PHP
PHP7 其他语言层面的修改
Mar 09 PHP
详解thinkphp5+swoole实现异步邮件群发(SMTP方式)
Oct 13 #PHP
详解PHP字符串替换str_replace()函数四种用法
Oct 13 #PHP
浅谈PHP接入(第三方登录)QQ登录 OAuth2.0 过程中遇到的坑
Oct 13 #PHP
PHP长网址与短网址的实现方法
Oct 13 #PHP
如何直接访问php实例对象中的private属性详解
Oct 12 #PHP
thinkphp中的多表关联查询的实例详解
Oct 12 #PHP
laravel 5异常错误:FatalErrorException in Handler.php line 38的解决
Oct 12 #PHP
You might like
php中将地址生成迅雷快车旋风链接的代码[测试通过]
2011/04/20 PHP
如何在smarty中增加类似foreach的功能自动加载数据
2013/06/26 PHP
php实现word转html的方法
2016/01/22 PHP
php实现留言板功能(会话控制)
2017/05/23 PHP
php-fpm超时时间设置request_terminate_timeout资源问题分析
2019/09/27 PHP
Aliyun Linux 编译安装 php7.3 tengine2.3.2 mysql8.0 redis5的过程详解
2020/10/20 PHP
javascript 日期常用的方法
2009/11/11 Javascript
js 效率组装字符串 StringBuffer
2009/12/23 Javascript
JavaScript对象、属性、事件手册集合方便查询
2010/07/04 Javascript
javascript 使td内容不换行不撑开
2012/11/29 Javascript
js中数组排序sort方法的原理分析
2014/11/20 Javascript
扒一扒JavaScript 预解释
2015/01/28 Javascript
JavaScript阻止浏览器返回按钮的方法
2015/03/18 Javascript
bootstrap输入框组使用方法
2017/02/07 Javascript
20行js代码实现的贪吃蛇小游戏
2017/06/20 Javascript
浅谈原型对象的常用开发模式
2017/07/22 Javascript
Vue2 模板template的四种写法总结
2018/02/23 Javascript
使用Node搭建reactSSR服务端渲染架构
2018/08/30 Javascript
ES10 特性的完整指南小结
2019/03/04 Javascript
vue+ESLint 配置保存 自动格式化代码
2020/03/17 Javascript
[59:30]完美世界DOTA2联赛PWL S3 access vs LBZS 第二场 12.20
2020/12/23 DOTA
Python编程之多态用法实例详解
2015/05/19 Python
python查看FTP是否能连接成功的方法
2015/07/30 Python
Python实现的计算马氏距离算法示例
2018/04/03 Python
python 统计一个列表当中的每一个元素出现了多少次的方法
2018/11/14 Python
Python实现八皇后问题示例代码
2018/12/09 Python
python遍历文件目录、批量处理同类文件
2019/08/31 Python
python GUI库图形界面开发之PyQt5控件数据拖曳Drag与Drop详细使用方法与实例
2020/02/27 Python
详解HTML5中CSS外观属性
2020/09/10 HTML / CSS
俄罗斯最大的在线珠宝大卖场:Nebo
2019/12/08 全球购物
2014年服务行业工作总结
2014/11/18 职场文书
2014年社区个人工作总结
2014/12/02 职场文书
2014年个人工作总结模板
2014/12/15 职场文书
中学教师师德师风承诺书
2015/04/28 职场文书
2016个人廉洁自律承诺书
2016/03/25 职场文书
iOS 16进一步确认,一共支持16款iPhone
2022/04/28 数码科技