首页 > 系统相关 >PHP7实现多进程

PHP7实现多进程

时间:2022-11-25 12:39:30浏览次数:37  
标签:fork PHP 实现 pid number 进程 pcntl PHP7


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

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

以前PHP群里的一位大神曾指导说后台PHP想进阶必然避不开多进程,正好公司里的守护进程也应用了PHP的多进程,结合着谷哥的各种资料和手册,总算理解了多进程。

要实现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 }

 

 

标签:fork,PHP,实现,pid,number,进程,pcntl,PHP7
From: https://blog.51cto.com/u_13940603/5886317

相关文章

  • PHP7的内核CGI与FastCGI
    CGI:是WebServer与WebApplication之间数据交换的一种协议。FastCGI:同CGI,是一种通信协议,但比CGI在效率上做了一些优化。PHP-CGI:是PHP(WebApplication)对WebSe......
  • PHP 中使用 TUS 协议来实现大文件的断点续传
    在现代网站应用中,上传文件是非常常见的。在任何语言中,通过使用一些工具,都可以实现文件上传的功能。但是,如果处理大文件上传的需求,还是有点麻烦的。 假如你此时正在上传一个......
  • Mysql主从同步的实现原理与配置
    1、什么是mysql主从同步?当master(主)库的数据发生变化的时候,变化会实时的同步到slave(从)库。 2、主从同步有什么好处?水平扩展数据库的负载能力。容错,高可用。Failover(失......
  • 令牌桶限流思路分享(PHP+Redis实现机制)
    一、场景描述 在开发接口服务器的过程中,为了防止客户端对于接口的滥用,保护服务器的资源,通常来说我们会对于服务器上的各种接口进行调用次数的限制。比如对于某个用户,他......
  • php调取摄像头实现拍照功能
    最近做的商户后台要实现调取摄像头拍摄用户打卡照片的功能,找资料研究了下,终于黄天不负有心人,成功了,下面我分步骤将代码贴出来,希望能有帮助。代码有点多,但是每一步都很好理解......
  • php与Redis实现一个100万用户的投票项目,实现实时查看投票情况?
    微信分享里总是有一些亲子活动,或者参加某些大赛需要进行投票,而面向的是所有人都可以参与,或者有限制一个人每天能投票同一个参与者3票之类的。。。这些应用场景有很多。假如......
  • php运用无限级分类实现评论及回复功能
    经常在各大论坛或新闻板块详情页面下边看到评论功能,当然不单单是直接发表评论内容那么简单,可以对别人的评论进行回复,别人又可以对你的回复再次评论或回复,如此反复,理论上可以......
  • go实现投票并实时打印投票信息
    packagemainimport"fmt"varstudents[]Studentvarflagbool=truetypeStudentstruct{noint//候选人编号namestring//候选热姓名countint//得票数}fun......
  • PHP+Redis实现分页
    废话少说,上代码吧<?phpclassRedisPage{protected$_redis;protected$_redis_ip;protected$_redis_port;protected$_redis_db;protected$_has......
  • 使用Xenon实现MySQL高可用集群
    使用Xenon实现MySQL高可用集群1、Xenon介绍 https://github.com/radondb/xenon#VIP就是对外提供服务的IP,比如jdbc配置就是写这个VIPxenon架构介绍 ,每个MySQL节点安装......