PHP多进程编程

使用多进程的优点:

    1. 使用多进程, 子进程结束以后, 内核会负责回收资源
    2. 使用多进程,子进程异常退出不会导致整个进程Thread退出. 父进程还有机会重建流程.
    3. 一个常驻主进程, 只负责任务分发, 逻辑更清楚.

PHP中实现多进程,Let's Go.

我们需要安装pcnt扩展

pcntl是process control的缩写,通常,php会默认安装这个扩展。使用phpinfo()函数查看扩展是否存在。

clipboard.png

使用pcntl_fork() 函数创建子进程

pcntl_fork作用就是创建和当前进程一样的子进程,这个子进程代码段和当前进程一模一样,但是拥有自己的数据段。看一个最简单的创建子进程的方法:

<?php
/**
 *  hedong
 * @date 2017-04-03
 */

$parentPid = getmypid(); // 获取父进程id $childPid = pcntl_fork(); // 创建子进程 switch($childPid) {
    case -1:
        print "创建子进程失败!".PHP_EOL;
        exit;
    case 0:
        print "我是子进程,进程ID:{$childPid}".PHP_EOL;
        break;
    default:
        print "我是父进程,进程ID:{$parentPid},子进程ID: {$childPid}".PHP_EOL;
}
?>
pcntl_fork()调用成功以后,一个程序变成了两个程序:一个程序得到的$pid变量值是0,它是子进程;另一个程序得到的$pid的值大于0,这个值是子进程的PID,它是父进程。

输出结果:

clipboard.png

子进程回收

① 阻塞方式
刚刚有ps么?一般我习惯用ps aux加上grep命令来查找运行着的后台进程。其中有一列STAT,标识了每个进程的运行状态。这里,我们关注状态Z:僵尸(Zombie)。当子进程比父进程先退出,而父进程没对其做任何处理的时候,子进程将会变成僵尸进程。僵尸进程虽然不占什么内存,但是很碍眼。(别忘了它们还占用着PID)

一般来说,在父进程结束之前回收挂掉的子进程就可以了。在pcntl扩展里面有一个pcntl_wait()函数,通过这个方法等待进程结束,然后回收已经结束的进程。


<?php
/**
 *  hedong
 * @date 2017-04-03
 */

$parentPid = getmypid(); // 获取父进程id $childPid = pcntl_fork(); // 创建子进程 switch($childPid) {
    case -1:
        print "创建子进程失败!".PHP_EOL;
        exit;
    case 0:
        print "我是子进程,进程ID:{$childPid}".PHP_EOL;
        break;
    default:
        pcntl_wait($status); // 子进程执行完后才执行父进程         print "我是父进程,进程ID:{$parentPid},子进程ID: {$childPid}".PHP_EOL;
}

② 非阻塞方式
阻塞方式失去了多进程的并行性。还有一种方法,既可以回收已经结束的子进程,又可以并行。这就是非阻塞的方式。

<?php
/**
 *  hedong
 * @date 2017-04-03
 */

for ($i = 1; $i <= 5; ++$i) {
    $pid = pcntl_fork(); // 创建子进程

    if (!$pid) {
        sleep(1);
        print "In child $i\n";
        exit($i);
    }
}

// pcntl_waitpid 第一个参数为 0 代表处理全部子进程

while (pcntl_waitpid(0, $status) != -1) {
    $status = pcntl_wexitstatus($status);
    echo "Child $status completed\n";
}

如果父进程先挂了怎么办?

会发生什么?什么也不会发生,子进程依旧还在运行。但是这个时候,子进程会被交给1号进程,1号进程成为了这些子进程的继父。1号进程会很好地处理这些进程的资源,当它们结束时1号进程会自动回收资源。所以,另一种处理僵尸进程的临时办法是关闭它们的父进程。

最后需要注意的:

进程控制不能被应用在Web服务器环境,当其被用于Web服务环境时可能会带来意外的结果。 -- 摘自PHP手册

参考:

http://www.hackingwithphp.com/16/1/3/getting-into-multiprocessing

http://www.jb51.net/article/71232.htm

http://www.laruence.com/2009/06/11/930.html

http://imhuchao.com/596.html

https://www.pureweber.com/article/php-multi-process-programming-preview/

clipboard.png

关注我的公众号,一起成长

1 篇内容引用
96 声望
10 粉丝
0 条评论
推荐阅读
PHP执行外部程序的方法
在一些特殊情况下,会使用PHP调用外部程序执行,比如:调用shell命令、shell脚本、可执行程序等等,今天在源码中了解了一下PHP执行外部程序的方法,借此机会顺便整理一下。

Jackwoo2阅读 6.9k

php实现只需要一个QQ号就可以获得用户信息
{代码...} DEMO:[链接]此处输入你的QQ号

TANKING27阅读 7.3k评论 5

初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go4阅读 1.7k评论 2

封面图
一分钟搞明白!快速掌握 Go WebAssembly
最近因为各种奇怪的原因,更多的接触到了 WebAssembly。虽然之前很多博客也翻过写过各种文章,但总感觉欠些味道。于是今天梳理了一版,和大家一起展开学习。

煎鱼4阅读 2.1k

面试官:请说一下如何优化结构体的性能?
使用内存对齐机制优化结构体性能,妙啊!前言之前分享过2篇结构体文章:10秒改struct性能直接提升15%,产品姐姐都夸我好棒 和 Go语言空结构体这3种妙用,你知道吗? 得到了大家的好评。这篇继续分享进阶内容:结...

王中阳Go4阅读 3.8k评论 2

封面图
Laravel入门及实践,快速上手ThinkSNS+二次开发
【摘要】自从ThinkSNS+不使用ThinkPHP框架而使用Laravel框架之后,很多人都说技术门槛抬高了,其实你与TS+的距离仅仅只是学习一个新框架而已,所以,我们今天来说说Laravel的入门。

ThinkSNS1阅读 2.4k

我让chatGPT用PHP写一个MVC框架,不仅写出来,还能跑!
没想到写出来的框架确实挺简单的,但是又没觉得哪里不对,于是我尝试把这个框架放到服务器试试能不能跑起来,最后还真的可以跑起来,为了让大家能够看到这个框架的演示,我直接爬一个热搜,然后便于展示数据。

TANKING1阅读 1.7k

封面图
96 声望
10 粉丝
宣传栏