Swoole Process多进程通信的实现

作者: 温新

分类: 【高性能PHP】

阅读: 2141

时间: 2021-04-20 15:34:32

Swoole Process多进程通信的实现

本篇学习将基于 Swoole Process模块实现进程间的通信。先来看看通过 PHP多进程间的通信 或许更容易理解些。

管道通信

文件:d7.php

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Swoole\Process</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">Swoole\Coroutine\run</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">/**</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">* new Process(); 创建子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">* @param callbale $function 子进程创建后执行的函数</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">* @param bool $redirect_stdin_stdout 重定向子进程的标准输入和输出</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">* @param int $pipe_type 创建管道 </span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">* @param bool $enable_coroutine 是否启用协程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">**/</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$proc</span>){</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 将管道到出为 Coroutine\Socket 对象后,</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 用Coroutine\socket 对象的方法进程间通讯</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$socket</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$proc</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">exportSocket</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 接收数据</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$socket</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">recv</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 发送数据</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$socket</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">send</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"Son:hi,主进程,我是子进程,已收到消息,我今天保证把碗洗的干干净净\n"</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// sleep(3);</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"我是子进程,我的使命结束了\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">true</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 启动子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">start</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 父进程使用协程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">run</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span>() <span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$socket</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">exportSocket</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$socket</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">send</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"Father:hello 子进程,我是父进程,今天你必须把碗洗了\n"</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$socket</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">recv</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">});</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 回收结束运行的子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">wait</span>(<span style="box-sizing: border-box;color: rgb(34, 17, 153)">true</span>);</span>

运行文件并查看结果

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">d7</span>.<span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    </span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 结果</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">hello</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">子进程,我是父进程,今天你必须把碗洗了</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">我是子进程,我的使命结束了</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">hi,主进程,我是子进程,已收到消息,我今天保证把碗洗的干干净净</span></span>

对于输出结果有没有感到一丝疑问?我是子进程,我的使命结束了在子进程中先自行了,如果有此疑问,不妨打开sleep的注释再来看看结果。

异步通信

文件:d8.php

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Swoole\Process</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">Swoole\Coroutine\run</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> (<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>){</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建socket事件监听</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Swoole\Event</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">add</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">pipe</span>, <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pipe</span>) <span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>){</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 通过管道从主进程中读取数据</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$cmd</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">read</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(51, 0, 170)">ob_start</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 执行外部程序并且显示原始输出</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(51, 0, 170)">passthru</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$cmd</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$res</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">ob_get_clean</span>() <span style="box-sizing: border-box;color: rgb(152, 26, 26)">?</span> : <span style="box-sizing: border-box;color: rgb(170, 17, 17)">' '</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$res</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">trim</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$res</span>) . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'. worker pid:'</span> . <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">pid</span> . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 将数据写入管道</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">write</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$res</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 退出子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(119, 0, 136)">exit</span>(<span style="box-sizing: border-box;color: rgb(17, 102, 68)">0</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    });</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">true</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 启动进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">start</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 主进程将数据通过管道发送给子子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">write</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'php --version'</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 从子进程中读取数据</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$msg</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">read</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'result from worker :'</span> . <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$msg</span>;</span>

执行并查看结果

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">d8</span>.<span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    </span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 结果</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">result</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">from</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">worker</span> :<span style="box-sizing: border-box;color: rgb(0, 0, 0)">PHP</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">8.0</span>.<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span> (<span style="box-sizing: border-box;color: rgb(0, 0, 0)">cli</span>) (<span style="box-sizing: border-box;color: rgb(0, 0, 0)">built</span>: <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Mar</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">31</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">2021</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">23</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">05</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">27</span>) ( <span style="box-sizing: border-box;color: rgb(0, 0, 0)">NTS</span> )</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">Copyright</span> (<span style="box-sizing: border-box;color: rgb(0, 0, 0)">c</span>) <span style="box-sizing: border-box;color: rgb(0, 0, 0)">The</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">PHP</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Group</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">Zend</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Engine</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">v4</span>.<span style="box-sizing: border-box;color: rgb(17, 102, 68)">0.1</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Copyright</span> (<span style="box-sizing: border-box;color: rgb(0, 0, 0)">c</span>) <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Zend</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Technologies</span>. <span style="box-sizing: border-box;color: rgb(0, 0, 0)">worker</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">pid</span>:<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1665</span></span>

如有错误,欢迎指正,一起交流学习。

请登录后再评论