浅析PHP7的多进程及实例源码


Posted in PHP onApril 14, 2019

准备

我们都知道PHP是单进程执行的,PHP处理多并发主要是依赖服务器或PHP-FPM的多进程及它们进程的复用,但PHP实现多进程也意义重大,尤其是在后台Cli模式下处理大量数据或运行后台DEMON守护进程时,多进程的优势不用多说。

PHP的多线程也曾被人提及,但进程内多线程资源共享和分配的问题难以解决。PHP也有多线程想关的扩展 pthreads ,但据说不太稳定,且要求环境为线程安全,所用不多。

以前PHP群里的一位大神曾指导说后台PHP想进阶必然避不开多进程,正好公司里的守护进程也应用了PHP的多进程,结合着谷哥的各种资料和手册,总算理解了多进程,并自己写了一个小demo(在linux系统上实现的),用此文总结一下,如有错漏,谢谢提出。

要实现PHP的多进程,我们需要两个扩展 pcntl 和 posix,安装方法这里不再赘述。

在php中我们使用pcntl_fork()来创建多进程(在*NIX系统的C语言编程中,已有进程通过调用fork函数来产生新的进程)。fork出来新进程则成为子进程,原进程则成为父进程,子进程拥有父进程的副本。这里要注意:

• 子进程与父进程共享程序正文段

• 子进程拥有父进程的数据空间和堆、栈的副本,注意是副本,不是共享

• 父进程和子进程将继续执行fork之后的程序代码

• fork之后,是父进程先执行还是子进程先执行无法确认,取决于系统调度(取决于信仰)

这里说子进程拥有父进程数据空间以及堆、栈的副本,实际上,在大多数的实现中也并不是真正的完全副本。更多是采用了COW(Copy On Write)即写时复制的技术来节约存储空间。简单来说,如果父进程和子进程都不修改这些 数据、堆、栈 的话,那么父进程和子进程则是暂时共享同一份 数据、堆、栈。只有当父进程或者子进程试图对 数据、堆、栈 进行修改的时候,才会产生复制操作,这就叫做写时复制。

在调用完pcntl_fork()后,该函数会返回两个值。在父进程中返回子进程的进程ID,在子进程内部本身返回数字0。由于多进程在apache或者fpm环境下无法正常运行,所以大家一定要在php cli环境下执行代码。

创建子进程

创建PHP子进程是多进程的开始,我们需要pcntl_fork()函数;

fork函数详解

pcntl_fork() — 在当前进程当前位置产生分支(子进程)。此函数创建了一个新的子进程后,子进程会继承父进程当前的上下文,和父进程一样从pcntl_fork() 函数处继续向下执行,只是获取到的pcntl_fork() 的返回值不同,我们便能从判断返回值来区分父进程和子进程,分配父进程和子进程去做不同的逻辑处理。

pcntl_fork() 函数成功执行时会在父进程返回子进程的进程id(pid),因为系统的初始进程init进程的pid为1,后来产生进程的pid都会大于此进程,所以我们可以通过判断pcntl_fork()的返回值大于1来确实当前进程是父进程;而在子进程中,此函数的返回值会是固定值0,我们也可以通过判断pcntl_fork()的返回值为0来确定子进程;而pcntl_fork()函数在执行失败时,会在父进程返回-1,当然也不会有子进程产生。

fork进程实例

fork子进程

$ppid = posix_getpid();

$pid = pcntl_fork();

if ($pid == -1) {

  throw new Exception('fork child process fail');

} elseif ($pid > 0) {

  cli_set_process_title("我是父 process,pid is : {$ppid}.");

  sleep(30);

} else {

  $cpid = posix_getpid();

  cli_set_process_title("我是 {$ppid} 子的 process,我的 process pid is : {$cpid}.");

  sleep(30);

}

说明:

posix_getpid():返回当前进程 id

cli_set_process_title('进程名称'):为当前进程取一个响亮的名字。

运行这个例子,我们便能看到当前两个PHP进程了。

www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ ps aux|grep -v grep |grep 我

www   18026 0.5 1.2 204068 25772 pts/0  S+  14:08  0:00 我是父 process,pid is : 18026.

www   18027 0.0 0.3 204068 6640 pts/0  S+  14:08  0:00 我 18026 子的 process,我的 process pid is : 18027. 

第一段代码,在程序从pcntl_fork()后父进程和子进程将各自继续往下执行代码:

$pid = pcntl_fork();

if( $pid > 0 ){

 echo "我是父亲".PHP_EOL;

} else if( 0 == $pid ) {

 echo "我是儿子".PHP_EOL;

} else {

 echo "fork失败".PHP_EOL;

} 

结果:

www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ php 123.php

我是父亲

我是儿子

第二段代码,用来说明子进程拥有父进程的数据副本,而并不是共享:

// 初始化一个 number变量 数值为1

$number = 1;

$pid = pcntl_fork();

if ($pid > 0) {

  $number += 1;

  echo "我是父亲,number+1 : { $number }" . PHP_EOL;

} else if (0 == $pid) {

  $number += 2;

  echo "我是儿子,number+2 : { $number }" . PHP_EOL;

} else {

  echo "fork失败" . PHP_EOL;

}

结果

www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ php 1234.php

我是父亲,number+1 : { 2 }

我是儿子,number+2 : { 3 }
PHP 相关文章推荐
使用sockets:从新闻组中获取文章(三)
Oct 09 PHP
PHP3 safe_mode 失效漏洞
Oct 09 PHP
COM in PHP (winows only)
Oct 09 PHP
网页游戏开发入门教程三(简单程序应用)
Nov 02 PHP
php URL验证正则表达式
Jul 19 PHP
php切割页面div内容的实现代码分享
Jul 31 PHP
解析phpstorm + xdebug 远程断点调试
Jun 20 PHP
php操作xml
Oct 27 PHP
使用PHP把HTML生成PDF文件的几个开源项目介绍
Nov 17 PHP
PHP中Memcache操作类及用法实例
Dec 12 PHP
Laravel 5.1 on SAE环境开发教程【附项目demo源码】
Oct 09 PHP
PHP如何根据文件头检测文件类型实例代码
Oct 14 PHP
什么是PHP7中的孤儿进程与僵尸进程
Apr 14 #PHP
php intval函数用法总结
Apr 14 #PHP
PHP中上传文件打印错误错误类型分析
Apr 14 #PHP
PHP扩展Swoole实现实时异步任务队列示例
Apr 13 #PHP
php+ajax实现商品对比功能示例
Apr 13 #PHP
PHP开发的文字水印,缩略图,图片水印实现类与用法示例
Apr 12 #PHP
详解PHP素材图片上传、下载功能
Apr 12 #PHP
You might like
PHP 线程安全与非线程安全版本的区别深入解析
2013/08/06 PHP
C/S和B/S两种架构区别与优缺点分析
2014/10/23 PHP
php绘制一条弧线的方法
2015/01/24 PHP
PHP  实现等比压缩图片尺寸和大小实例代码
2016/10/08 PHP
PHP-FPM运行状态的实时查看及监控详解
2016/11/18 PHP
PHP中如何使用Redis接管文件存储Session详解
2018/11/28 PHP
php实现微信分享朋友链接功能
2019/02/18 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
javascript 读取XML数据,在页面中展现、编辑、保存的实现
2009/10/27 Javascript
基于jquery实现点击左右按钮图片横向滚动
2013/04/11 Javascript
js和jquery如何获取图片真实的宽度和高度
2014/09/28 Javascript
javascript手工制作悬浮菜单
2015/02/12 Javascript
jQuery使用正则表达式限制文本框只能输入数字
2016/06/18 Javascript
jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承
2016/12/06 Javascript
JS中parseInt()和map()用法分析
2016/12/16 Javascript
vue+axios实现登录拦截的实例代码
2017/05/22 Javascript
详解如何使用 vue-cli 开发多页应用
2017/12/16 Javascript
vue 组件 全局注册和局部注册的实现
2018/02/28 Javascript
微信小程序之批量上传并压缩图片的实例代码
2018/07/05 Javascript
JavaScript中为事件指定处理程序的五种方式分析
2018/07/27 Javascript
Vue实现6位数密码效果
2018/08/18 Javascript
使用python获取CPU和内存信息的思路与实现(linux系统)
2014/01/03 Python
Python模块相关知识点小结
2020/03/09 Python
Pytorch生成随机数Tensor的方法汇总
2020/09/09 Python
python 实现aes256加密
2020/11/27 Python
利用Python实现学生信息管理系统的完整实例
2020/12/30 Python
HTML5 WebGL 实现民航客机飞行监控系统
2019/07/25 HTML / CSS
HTML5 script元素async、defer异步加载使用介绍
2013/08/23 HTML / CSS
HTML5 canvas 瀑布流文字效果的示例代码
2018/01/31 HTML / CSS
详解如何解决canvas图片getImageData,toDataURL跨域问题
2018/09/17 HTML / CSS
校园门卫岗位职责
2013/12/09 职场文书
外贸英语专业求职信范文
2013/12/25 职场文书
2014年入党积极分子党课学习心得体会模板
2014/04/03 职场文书
2016年世界人口日宣传活动总结
2016/04/05 职场文书
拒绝盗图!教你怎么用python给图片加水印
2021/06/04 Python
科学家研发出新型速效酶,可在 24 小时内降解塑料制品
2022/04/29 数码科技