swoole文档:Swoole 文档
process子进程和父进程之间通信,依靠监听。子进程和父进程分别做监听。父进程写入信息,子进程监听接收。子进程向父进程写入,调用父进程监听。
子进程向父进程写入信息有两种方式,一种调用write写入管道,一种是直接输出写入管道。在创建进程的时候控制。
一 调用write写入管道
function test3()
{
$p = new Swoole\Process(function ($worker) {
Swoole\Event::add($worker->pipe, function () use ($worker) {
$data = $worker->read();
echo "sub:" . $data . PHP_EOL;
$data = 'worker:' . $data;
$worker->write($data); //写入父线程 2
});
}, false, 2);
$p->start();
Swoole\Event::add($p->pipe, function () use ($p) {
$data = $p->read();
echo 'P:' . $data . PHP_EOL; //最终输出 3
});
$p->write('123'); //请求子线程 1
}
test3();
sub:123
P:worker:123
二 直接输出到管道
function test2()
{
$p = new Swoole\Process(function ($worker) {
Swoole\Event::add($worker->pipe, function () use ($worker) {
$data = $worker->read();
echo 'worker:' . $data . PHP_EOL; //直接写入父线程 2
});
}, true, 2);
$p->start();
Swoole\Event::add($p->pipe, function () use ($p) {
$data = $p->read();
echo 'P:' . $data . PHP_EOL; //最终输出 3
});
$p->write('123'); //请求子线程 1
}
test2();
P:worker:123
新建process之后,在其回调中创建的监听是子进程的监听,使用其对象创建的监听是父进程的监听。
三 其他
其实子进程不做监听也能收到父进程发送的信息,但是直接读信息和监听都存在的情况下,先执行直接读取的,可能监听不会执行。根据文档,监听必须在线程启动后设置。根据查的资料,event触发条件是句柄文件的改变,即类似于例子中的$p->pipe改变,否则不会触发。
使用event监听是异步的。看到b站上有个例子代码如下
public function onMessage(Swoole\WebSocket\Server $server, Swoole\WebSocket\Frame $frame)
{
$data = $frame->data;
$data = json_decode($data);
$cmd = $data['cmd']; //命令
$fd = $frame->fd;
$is_block = isset($data['is_block']) ? $data['is_block'] : 0;
if ($is_block) {
if (isset($this->process_list[$fd])) {
$process = $this->process_list[$fd];
} else {
//新建子进程
$process = new Swoole\Process([$this, 'do_time_process'], true, 2);
$process->start();
$this->process_list[$fd] = $process;
Swoole\Event::add($process->pipe, function () use ($process, $frame) {
$data = $process->read();
$this->server->push($frame->fd, $data);
});
}
$process->write($cmd);
sleep(1);
} else {
$this->process->write($cmd);
$data = $this->process->read();
$this->server->push($frame->fd, $data);
}
}
//子进程
public function do_time_process(Swoole\Process $worker)
{
$cmd = $worker->read();
//函数打开进程文件指针。打开一个指向进程的管道,该进程由派生指定的 command 命令执行而产生
$handle = popen($cmd, 'r');
Swoole\Event::add($worker->pipe, function () use ($worker, $handle) {
$cmd = $worker->read();
if ('exit' == $cmd) {
$worker->exit();
}
//向管道写入内容
fwrite($handle, $cmd);
});
//feof() 函数检查是否已到达文件末尾(EOF)
while (!feof($handle)) {
$str = fread($handle, 18192);
$worker->write($str); //向父进程写入
//echo $str;
}
}
do_time_process中设置event监听的目的是,在执行不会自己结束的命令时,可以再次设置命令执行退出等操作。比如linux中ping命令。还没测试好,本来想写个例子试试,但是按照以上内容写的,子进程中的监听一直没有被触发。
四 参考
【swoole 入门课程】https://www.bilibili.com/video/BV1dt411a7Tb?p=4&vd_source=f1bd3b5218c30adf0a002c8c937e0a27
swoole_event_add · Swoole文档 · 看云