PHP多进程讲解(八):匿名管道通信之proc_open
上一篇文章中,我们讲解了利用popen函数进行匿名管道通信,不过有个问题,就是该函数只能实现单向通信,也就是同时只能打开读通道或者写通道。今天要介绍的函数 proc_open
则可以实现双向通信。
在观看本文章之前,请先去了解下函数 proc_open
的基本用法,链接地址:proc_open
首先,我们创建 pipe-process.php
文件,内容如下:
<?php
$pid = getmypid();
echo '子进程PID:'.$pid.'|父进程数据:'.fgets(STDIN)."\n";
fwrite(STDERR, '我是从错误信息');
很简单,从标准输入读取数据,然后输出,另外写入一段数据到标准错误中。
然后,创建 pipe2.php
文件,内容如下:
<?php
$pid = getmypid();
echo "PID:{$pid}\n";
// 需要执行的命令
$command = '/usr/local/opt/php@7.2/bin/php pipe-process.php';
// 命令执行的目录
$cwd = '/Users/xiaoteng/work/test/';
$process = proc_open($command, [
// 标准输入
0 => ['pipe', 'r'],
// 标准输出
1 => ['pipe', 'w'],
// 标准错误流
2 => ['file', '/tmp/pipe2.log', 'a']
], $pipes, $cwd);
// 将数据传递给子进程
fwrite($pipes[0], '来自父进程的消息,当前时间:'.date('Y-m-d H:i:s')."\n");
fclose($pipes[0]);
// 读取子进程的标准输出
$line = fgets($pipes[1]);
fclose($pipes[1]);
echo "读取到子进程的消息,内容:\n";
echo $line."\n";
proc_close($process);
简单解析下内容。通过 proc_open
函数创建一个子进程,这个子进程就是 php pipe-process.php
这个命令。在该函数的第二个参数中,我们指定了标准描述符,其中0,1,2分别代表的是标准输入,标准输出,标准错误,这个都是通用的。
这里的话,我们将0,1也就是标准输入和标准输出指定为 pipe
也就是管道,因为我们还需要通过管道通信。然后将2也就是标准错误的处理类型指定为file,也就是说,子进程的执行错误输出将会保存到这个file中,在这里的话,也就是 /tmp/pipe2.log
这个文件中。至于该参数中的 r
, w
, a
这些其实熟悉文件操作的小伙伴应该都知道的吧,不知道的话可以看下 fopen
这个函数。
proc_open
函数的第三个参数,也就是这里的 $pipes
,这是个引用变量,在函数执行后,该变量是标准描述符的具体的文件指针,其中 $pipes[0]
是标准输入的指针, $pipes[1]
是标准输出的指针。
OK,我们来执行下:
~ php pipe2.php
PID:84980
读取到子进程的消息,内容:
子进程PID:84981|父进程数据:来自父进程的消息,当前时间:2020-08-08 09:48:28
可以看到,子进程成功的接收到父进程的消息,父进程成功的读取到了子进程的输出。这样的话,我们就完成了一个双向的通信。我们在来看下标准错误输出:
~ cat /tmp/pipe2.log
我是从错误信息
可以看到,在子进程中写入标准错误的数据被保存到了 /tmp/pipes.log
这个文件中了。
这就是匿名管道的双向通信。可以看到的是,proc_open
函数相比较 popen
更加强大。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭