14.进程间通信

进程间通信

进程间通信(IPC,Inter-Process Communication),指至少两个进程或线程间传送数据或信号的一些技术或方法。每个进程都有自己的一部分独立的系统资源,彼此是隔离的。为了能使不同的进程互相访问资源并进 行协调工作,才有了进程间通信。

进程通信有如下的目的:
数据传输: 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M之间;
共享数据: 多个进程想要操作共享数据,一个进程对数据的修改,其他进程应该立刻看到; 系统进行进程间通信(IPC)的时候,可用的方式包括管道、命名管道、消息队列、信号、信号量、共享内存、套接字(socket)等形式。

消息队列

关于消息队列实际上是一种思想或者说是策略,而并非是某一个程序所独有,我们可以通过消息队列让php与java等其他语言程序对接交互;并且值得一提的是,最简单的实现方式就是通过与一个文件记录信息,然后 通过另一个进程循环读取这个文件即可;
比如可以利用 file_put_contents 与 file_get_contents 就可以简单实现,不过我们这里讲的是如何利用系统的消息队列

示例演示

注意php操作系统内核的消息队列主要是使用sysvmsg扩展,以及相关函数如下:

函数连接
ftokhttps://php.golaravel.com/function.ftok.html
msg_get_queuehttps://php.golaravel.com/function.msg-get-queue.html
msg_receivehttps://php.golaravel.com/function.msg-receive.html
msg_remove_queuehttps://php.golaravel.com/function.msg-remove-queue.html
msg_sendhttps://php.golaravel.com/function.msg-send.html
<?php

//父进程跟子进程实现消息发送 
$msg_key = ftok(__DIR__, 'u'); //注意在php创建消息队列,第二个参数会直接转成字符串,可能会导致通讯失败
$msg_queue = msg_get_queue($msg_key);
$pid = pcntl_fork();
if ($pid == 0) {
    // 子进程发送消息
    msg_send($msg_queue, 10, "我是子进程发送的消息");
    exit();
} else if ($pid) {
    msg_receive($msg_queue, 10, $message_type, 1024, $message);
    var_dump($message);
    // 父进程接收消息
    pcntl_wait($status);
    msg_remove_queue($msg_queue);
}

也可以用不同的程序访问操作:

<?php

$msg_key = ftok(__DIR__, 'u'); //注意在php创建消息队列,第二个参数会直接转成字符串,可能会导致通讯失败
$msg_queue = msg_get_queue($msg_key);
msg_receive($msg_queue, 10, $message_type, 1024, $message);
var_dump($message);
// 父进程接收消息 
msg_remove_queue($msg_queue);

<?php
$msg_key = ftok(__DIR__,'u'); //注意在php创建消息队列,第二个参数会直接转成字符串,可能会导致通讯失败 
$msg_queue = msg_get_queue($msg_key); 
msg_send($msg_queue, 10, "我是while");

注意:msg_receive在没有接收到信息的时候会是一个阻塞的状态

函数介绍

写信息:msg_send ( resource $queue , int $msgtype , mixed $message [, bool $serialize = true [, bool KaTeX parse error: Expected 'EOF', got '&' at position 24: … = true [, int &̲errorcode ]]] )

第1个参数 : resource $queue 表示要写入的消息队列资源。
第2个参数 : int $msgtype 表示写入消息队列的 消息类型,这个参数是 配合 msg_receive读取消息队列函数 使用的,下面会说。
第3个参数 : mixed $message 你要发送的信息,最大为 65536 个字节。

读信息:msg_receive ( resource $queue , int KaTeX parse error: Expected 'EOF', got '&' at position 22: …dmsgtype , int &̲msgtype , int KaTeX parse error: Expected 'EOF', got '&' at position 17: …axsize , mixed &̲message [, bool $unserialize = true [, int KaTeX parse error: Expected 'EOF', got '&' at position 18: …ags = 0 [, int &̲errorcode ]]] )

第1个参数 : resource $queue 表示要读取的消息队列资源。
第2个参数 : int $ desiredmsgtype 读取的消息类型。这个参数为 0 的时候,你可以读取 msg_send 以任意 消息类型 发送的消息。 如果此参数和你发送的某个消息类型相同,比如你有 2个消息,一个是通 过 1类型发送的,一个是通过2 类型发送的。你用 0 可以接收这两种消息 ,而你用 1 只能接收到 以1类型发送的消息。
第3个参数 : int&$msgtype 你读取到的信息,它发送时的消息类型会存储在该参数中。
第4个参数 : int $ maxsize 你以多大的字节去读取消息,如果这个值小于你要读取的内容的长度,你会读取失败。
第5个参数 : mixed&$message 读取的内容。

swoole官网实例
https://wiki.swoole.com/wiki/page/212.html

<?php

class SwooleTask {

    protected $queueId;
    protected $workerId;
    protected $taskId = 1;

    const SW_TASK_TMPFILE = 1; //tmp file
    const SW_TASK_SERIALIZE = 2; //php serialize
    const SW_TASK_NONBLOCK = 4; //task
    const SW_EVENT_TASK = 7;

    function __construct($key, $workerId = 0) {
        $this->queueId = msg_get_queue($key);
        if ($this->queueId === false) {
            throw new \Exception("msg_get_queue() failed.");
        }$this->workerId = $workerId;
    }

    protected static function pack($taskId, $data) {
        $flags = self::SW_TASK_NONBLOCK;
        $type = self::SW_EVENT_TASK;
        if (!is_string($data)) {
            $data = serialize($data);
            $flags |= self::SW_TASK_SERIALIZE;
        }if (strlen($data) >= 8180) {
            $tmpFile = tempnam('/tmp/', 'swoole.task');
            file_put_contents($tmpFile, $data);
            $data = pack('l', strlen($data)) . $tmpFile . "\0";
            $flags |= self::SW_TASK_TMPFILE;
            $len = 128 + 24;
        } else {
            $len = strlen($data);
        }return pack('lSsCCS', $taskId, $len, 0, $type, 0, $flags) . $data;
    }

    function dispatch($data) {
        $taskId = $this->taskId++;
        if (!msg_send($this->queueId, 2, self::pack($taskId, $data), false)) {
            return false;
        } else {
            return $taskId;
        }
    }

}

echo "Sending text to msg queue.\n";
$task = new SwooleTask(822094551, 1);
//普通字符串 
$task->dispatch("Hello from PHP!");
<?php

$server = new Swoole\Server("0.0.0.0", 9000); //创建server对象
$server->set(['worker_num' => 1, //设置进程
    'task_worker_num' => 1, //task进程数
]);
//消息发送过来
$server->on('receive', function (swoole_server $server, int $fd, int $reactor_id, string $data) {
    $server->task(7);
    $server->send($fd, 1);
});
//ontask事件回调
$server->on('task', function (swoole_server $server, $task_id, $form_id, $data) {
    echo "接受到信息\n";
    var_dump($server->worker_id);
    $server->sendMessage("Task数据", 2); // 0 ~ (worker_num + task_worker_num - 1)
    $server->finish("执行完毕");
});
$server->on('finish', function ($server, $task_id, $data) {
    
});
$server->on('PipeMessage', function (swoole_server $server, $src_worker_id, $message) {
    echo "\n接收到数据\n";
    var_dump($message);
});
//服务器开启 
$server->start();

在worker中实现task

// io\src\Reactor\Swoole\MulitEndhancedTask\Traits\TaskTraits.php

task的作用

注意关于swoole的task虽然有体现这种异步的效果,但是并不意味这它是用来替代消息中间件的; swoole中的task最大的特点在于帮助我们处理一些耗时任务的业务逻辑,完成之后就会通知给相应的进程; 而消息中间件-》在实际的工作中我们可能会考虑消息的优先级,延迟任务,存储,应答等等;

swoole中的编程需知

https://wiki.swoole.com/wiki/page/500.html
建议大家在使用的时候一定要关注这些内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值