利用管道实现进程间通信

原文链接:https://segmentfault.com/a/1190000002946586
Process 的通信方式有两种

管道
swoole_process->write(string $data);
swoole_process->read(int $buffer_size=8192);

消息队列
swoole_process->useQueue();
swoole_process->push(string $data);
swoole_process->pop(int $maxsize = 8192);

我们先说说管道

管道通讯
这里我们要再次的提及进程的创建 new swoole_process
大家请看这里 进程的创建
第一个参数是回调函数,不说了
第二个参数含义等会我会结合例子来说
第三个参数是默认的 true,意思是创建管道,大家还记得回调函数里我特意将$worker输出看到的内容吗?

object(swoole_process)#1 (3) {
  ["pipe"]=>
  int(3)
  ["callback"]=>
  string(26) "callback_function_we_write"
  ["pid"]=>
  int(5445)
}
关键是这里的 pipe 这个就是本进程的管道id
我们可以这样理解

每次创建一个进程后,就会随之创建一个管道,主进程想和哪一个进程通信,就向那个进程的管道写入/读取数据。

ok,我们看看代码

<?php
$redirect_stdout = false;// 重定向输出  ; 这个参数用途等会我们看效果
$worker_num = 2;//进程数量
$workers = [];//存放进程用的
for($i = 0; $i < $worker_num; $i++){
    $process = new swoole_process('workerFunc',$redirect_stdout );
    $pid = $process->start();
    $workers[$pid] = $process;//将每一个进程的句柄存起来
}
// 这里是主进程哦。
foreach($workers as $pid => $process){// $process 是子进程的句柄
    $process->write("hello worker[$pid]\n");//子进程句柄向自己管道里写内容                  $process->write($data);
    echo "From Worker: ".$process->read();//子进程句柄从自己的管道里面读取信息    $process->read();
    echo PHP_EOL.PHP_EOL;
 }

function workerFunc(swoole_process $worker){//这里是子进程哦
    $recv = $worker->read();
    echo PHP_EOL. "From Master: $recv\n";
    //send data to master
    $worker->write("hello master , this pipe  is ". $worker->pipe .";  this  pid  is ".$worker->pid."\n");
    sleep(2);
    $worker->exit(0);
}
贴上运行结果

From Master: hello worker[8205]

From Worker: hello master , this pipe  is 3;  this  pid  is 8205



From Master: hello worker[8206]

From Worker: hello master , this pipe  is 5;  this  pid  is 8206
喔,通讯是这样的。
首先 将所有的子进程的句柄都存到 主进程的一个数组里,数组下标就是pid。
当主进程想和哪个进程通讯,就使用那个句柄向对应管道里面 写/读 数据,这样就实现了进程间的通讯。

接着,我们稍微改一下,看看运行效果

$redirect_stdout = true;// 重定向输出  注意 这次我改成 true 了,其他没变
$worker_num = 2;//进程数量
$workers = [];//存放进程用的
for($i = 0; $i < $worker_num; $i++){
    $process = new swoole_process('workerFunc',$redirect_stdout );
    $pid = $process->start();
    $workers[$pid] = $process;//将每一个进程的句柄存起来
}

// 这里是主进程哦。
foreach($workers as $pid => $process){// $process 是子进程的句柄
    $process->write("hello worker[$pid]\n");//子进程句柄向自己管道里写内容                $process->write($data);
    echo "From Worker: ".$process->read();//子进程句柄从自己的管道里面读取信息    $process->read();
    echo PHP_EOL.PHP_EOL;
 }

function workerFunc(swoole_process $worker){//这里是子进程哦
    $recv = $worker->read();
    echo PHP_EOL. "From Master: $recv\n";
    //send data to master
    $worker->write("hello master , this pipe  is ". $worker->pipe .";  this  pid  is ".$worker->pid."\n");
    sleep(2);
    $worker->exit(0);
}
输出结果

From Worker: 
From Master: hello worker[8007]



From Worker: 
From Master: hello worker[8008]
诶,不一样了有没有。我们再看看创建进程时第二个参数的说明

$redirect_stdin_stdout,重定向子进程的标准输入和输出。 启用此选项后,在进程内echo将不是打印屏幕,而是写入到管道。读取键盘输入将变为从管道中读取数据。 默认为阻塞读取。

我来说明一下,因为创建的时候指定了true,子进程中echo的内容就到了管道里面,而不是打印在屏幕上(这一点类似于php的ob缓存机制,大家想象一下)
前面说了,进程的通讯是通过从管道里面读/写数据实现的,而 子进程 里 echo 的内容被 重定向到管道里面了,所以,主进程从管道里读到的内容,就是 子进程中 echo 的 内容。
也就造成了上面的 输出结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值