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。

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

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

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

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

1
2
3
4
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为子进程的标记。我们可以通过对子进程标记来结束进程执行。所以我们可以将我们的代码修改为如下形式:

1
2
3
4
5
6
7
8
9
$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多进程编之pcntl_fork的实例详解的更多相关文章

  1. 【python3+request】python3+requests接口自动化测试框架实例详解教程

    转自:https://my.oschina.net/u/3041656/blog/820023 [python3+request]python3+requests接口自动化测试框架实例详解教程 前段时 ...

  2. JS hashMap实例详解

    链接:http://www.jb51.net/article/85111.htm JS hashMap实例详解 作者:囧侠 字体:[增加 减小] 类型:转载 时间:2016-05-26我要评论 这篇文 ...

  3. python+requests接口自动化测试框架实例详解

    python+requests接口自动化测试框架实例详解   转自https://my.oschina.net/u/3041656/blog/820023 摘要: python + requests实 ...

  4. Java中JSON字符串与java对象的互换实例详解

    这篇文章主要介绍了在java中,JSON字符串与java对象的相互转换实例详解,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JS ...

  5. jQuery对html元素的取值与赋值实例详解

    jQuery对html元素的取值与赋值实例详解 转载  2015-12-18   作者:欢欢   我要评论 这篇文章主要介绍了jQuery对html元素的取值与赋值,较为详细的分析了jQuery针对常 ...

  6. Java中JSON字符串与java对象的互换实例详解(转)

    http://www.jb51.net/article/90914.htm 在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要 ...

  7. Linux备份数据库,mysqldump命令实例详解

    mysqldump是mysql数据库中备份工具,用于将MYSQL服务器中的数据库以标准的sql语言的方式导出,并保存到文件中. 语法: mysqldump (选项) 选项: --add-drop-ta ...

  8. linux基础-磁盘阵列(RAID)实例详解

    磁盘阵列(RAID)实例详解 raid技术分类 软raid技术 硬raid技术 Raid和lvm的区别 为什么选择用raid RAID详解 RAID-0 RAID-1 RAID-5 Raid-10 R ...

  9. Cocos2d-x 3.X手游开发实例详解

    Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...

随机推荐

  1. (5)ps详解 (每周一个linux命令系列)

    (5)ps详解 (每周一个linux命令系列) linux命令 ps详解 引言:今天的命令是用来看进程状态的ps命令 ps 我们先看man ps ps - report a snapshot of t ...

  2. mysql 中sql的执行顺序

    文章转自 https://www.cnblogs.com/annsshadow/p/5037667.html https://www.cnblogs.com/yyjie/p/7788428.html ...

  3. MATLAB——神经网络sim仿真函数

  4. MariaDB CEO 痛斥云厂商从不回馈社区

    导读 MariaDB 首席执行官 Michael Howard 表示,亚马逊和 Oracle 将客户牢牢锁定.他还想知道 AWS 是否可能对 AWS MariaDB 实例动手脚,好让 AWS 自己的数 ...

  5. 使用Nginx来解决跨域的问题

    使用Nginx来解决跨域的问题 nginx的版本:(查看nginx命令: /usr/local/nginx/sbin/nginx -v) nginx/1.4.3 问题是:前端项目域名是 a.xxxx. ...

  6. node.js 基础一 安装

    1.下载 2.安装 3.查看版本 一 下载 下载地址:https://nodejs.org/zh-cn/download/ 二 安装 运行安装包:node-v8.9.2-x64.msi

  7. rook 入门理解

    参考:https://my.oschina.net/u/2306127/blog/1830356?from=timeline 1.Rook通过一个操作器(operator)完成后续操作,只需要定义需要 ...

  8. System.ServiceModel.CommunicationException: 接收HTTP 响应时错误发生

    具体错误信息例如以下: System.ServiceModel.CommunicationException: 接收对 http://110.110.110.110/TestService/TestS ...

  9. Spring Extensible XML

    Spring框架从2.0版本开始,提供了基于Schema风格的Spring XML格式用来定义bean的扩展机制.引入Schema-based XML是为了对Traditional的XML配置形式进行 ...

  10. 4.1《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)—目录结构

    Unix风格的目录结构通常使用一个目录名列表并用正斜杠分隔来表示,这样我们可以结合ls命令: $ ls /Users/mhartl/ruby 或者 $ ls /usr/local/bin 正如图20, ...