怎么在PHP中使用process模块创建子进程

本篇文章给大家分享的是有关怎么在PHP中使用process模块创建子进程,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

swoole中为我们提供了一个进程管理模块 Process,替换PHP的 pcntl 扩展,方便我们创建进程,管理进程,和进程间的通信。

怎么在PHP中使用process模块创建子进程

swoole提供了2种进程间的通信:

1、基于 unix socket 的管道 pipe。

2、基于 sysvmsg 的消息队列。

我们可以通过 new swoole_process() 快速的创建一个进程,默认会创建一个 SOCK_DGRAM 类型的管道,用于进程间的通信,当然可以设置成其他类型,也可以不创建。

一、通过同步阻塞管道进行进程间通信

<?php
$worker_process_nums=5;
$worker_process=[];

for($i=0;$i<$worker_process_nums;$i++){
//创建子进程
//默认为每个子进程创建一个管道,如果不想创建设置$pipe_type参数为false
//注意管道默认是同步阻塞,半双工,如果读取不到数据就会阻塞
$worker=newswoole_process(function(swoole_process$worker){
//注意,如果主进程中不写数据write(),那么子进程这里read()就会阻塞
$task=json_decode($worker->read(),true);

//进行计算任务
$tmp=0;
for($i=$task['start'];$i<$task['end'];$i++){
$tmp+=$i;
}

echo'子进程PID:',$worker->pid,'计算',$task['start'],'-',$task['end'],'结果:',$tmp,PHP_EOL;
//往管道中写入计算的结果
$worker->write($tmp);
//子进程退出
$worker->exit();
});

//保存子进程
$worker_process[$i]=$worker;

//启动子进程
$worker->start();
}

//往每个子进程管道中投递任务
for($i=0;$i<$worker_process_nums;$i++){
$worker_process[$i]->write(json_encode([
'start'=>mt_rand(1,10),
'end'=>mt_rand(50,100),
]));
}

//父进程监听子进程退出信号,回收子进程,防止出现僵尸进程
swoole_process::signal(SIGCHLD,function($sig){
//必须为false,非阻塞模式
while($ret=swoole_process::wait(false)){
echo"子进程PID:{$ret['pid']}退出\n";
}
});

二、通过 swoole_event_add 将管道设为异步,来进行通信

<?php
$worker_process_nums=5;
$worker_process=[];

for($i=0;$i<$worker_process_nums;$i++){
$worker=newswoole_process(function($worker){
//在子进程中给管道添加事件监听
//底层会自动将该管道设置为非阻塞模式
//参数二,是可读事件回调函数,表示管道可以读了
swoole_event_add($worker->pipe,function($pipe)use($worker){
$task=json_decode($worker->read(),true);

$tmp=0;
for($i=$task['start'];$i<$task['end'];$i++){
$tmp+=$i;
}
echo"子进程:{$worker->pid}计算{$task['start']}-{$task['end']}\n";
//子进程把计算的结果,写入管道
$worker->write($tmp);
//注意,swoole_event_add与swoole_event_del要成对使用
swoole_event_del($worker->pipe);
//退出子进程
$worker->exit();
});
});

$worker_process[$i]=$worker;

//启动子进程
$worker->start();
}

for($i=0;$i<$worker_process_nums;$i++){
$worker=$worker_process[$i];

$worker->write(json_encode([
'start'=>mt_rand(1,10),
'end'=>mt_rand(50,100),
]));

//主进程中,监听子进程管道事件
swoole_event_add($worker->pipe,function($pipe)use($worker){
$result=$worker->read();
echo"子进程:{$worker->pid}计算结果{$result}\n";
swoole_event_del($worker->pipe);
});
}

//父进程监听子进程退出信号,回收子进程,防止出现僵尸进程
swoole_process::signal(SIGCHLD,function($sig){
//必须为false,非阻塞模式
while($ret=swoole_process::wait(false)){
echo"子进程PID:{$ret['pid']}退出\n";
}
});

三、使用消息队列来完成进程间通信

<?php
$worker_process_nums=5;
$worker_process=[];

for($i=0;$i<$worker_process_nums;$i++){
//注意,这里将参数$pipe_type设为false,表示不创建管道
$worker=newswoole_process(function($worker){
$task=json_decode($worker->pop(),true);

$tmp=0;
for($i=$task['start'];$i<$task['end'];$i++){
$tmp+=$i;
}
echo"子进程:{$worker->pid}计算{$task['start']}-{$task['end']}\n";
$worker->push($tmp);
$worker->exit();
},false,false);

//使用消息队列,作为进程间的通信
//注意,消息队列是共享的
$worker->useQueue();

$worker_process[$i]=$worker;

//启动子进程
$worker->start();
}

for($i=0;$i<$worker_process_nums;$i++){
//只需用一个子进程发送消息即可,因为消息队列是共享的
$worker_process[0]->push(json_encode([
'start'=>mt_rand(1,10),
'end'=>mt_rand(50,100),
]));
}

//注意,这里要暂停,防止加入队列的任务,立刻被主进程读出来。
sleep(1);

for($i=0;$i<$worker_process_nums;$i++){
$result=$worker_process[0]->pop();
echo"计算结果:{$result}\n";
}

//父进程监听子进程退出信号,回收子进程,防止出现僵尸进程
swoole_process::signal(SIGCHLD,function($sig){
//必须为false,非阻塞模式
while($ret=swoole_process::wait(false)){
echo"子进程PID:{$ret['pid']}退出\n";
}
});

四、进程可以通过 signal 监听信号,和 alarm 设置定时器。

我们可以在父进程上设置监听信号,当子进程退出时,重新挂起子进程。

也可以设置定时器,通过 swoole_process::kill($pid, 0); 定时检测进程是否存活。

<?php
//每隔1秒触发SIGALAM信号
//注意,alarm不能和Timer同时使用
swoole_process::alarm(1000*1000,0);

swoole_process::signal(SIGALRM,function($signo){
static$cnt=0;
$cnt++;
echo"时钟定时信号\n";

if($cnt>10){
//清除定时器
swoole_process::alarm(-1);
}
});

swoole_process::signal(SIGINT,function($signo){
echo"我被ctrl+c了\n";

//退出主进程,不然将一直无法正常退出
exit(0);
});

以上就是怎么在PHP中使用process模块创建子进程,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注恰卡编程网行业资讯频道。

发布于 2021-03-21 22:39:00
收藏
分享
海报
0 条评论
172
上一篇:怎么在PHP中使用swoole编写一个echo服务器 下一篇:如何在Python中使用dict和defaultdict
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码