前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux进程通信之消息队列

Linux进程通信之消息队列

作者头像
北溟有鱼QAQ
发布2021-09-09 11:04:47
2.6K0
发布2021-09-09 11:04:47
举报
文章被收录于专栏:北溟有鱼QAQ北溟有鱼QAQ

Linux进程通信之IPC消息队列

首先消息队列是存放消息的队列,而队列则是一种先进先出的数据结构。

在PHP扩展中,封装了8个消息队列相关的函数,有 ftokmsg_get_queuemsg_queue_existsmsg_receivemsg_remove_queuemsg_sendmsg_set_queuemsg_stat_queue 具体的相关参数以及介绍,请查看PHP手册及相关文档 PHP手册之IPC

不同进程间消息队列通信

写进程demo21.php
代码语言:javascript
复制
//根据一个存在的文件和标识生成消息队列的key
$key = ftok('demo21.php','a');

//创建消息队列
$msgId = msg_get_queue($key);

//向消息队列中发送消息
msg_send($msgId,1,'test');

var_dump($msgId);

执行命令,查看结果,打印的是返回的消息队列id

在终端中输入 ipcs 查看是否创建并发送成功

可以看到上面插入了一条消息,可以反复重复以上命令,可以看到多条消息插入进行。如果有看的仔细的同学可能会有这样一个疑问,我明明写入的test是四个字节,为什么存入了11个字节,接下来我们使用strace -f -s 6550 php demo21.php 命令查看一下

通过执行上面的命令,我们可以看到,实际底层当中调用的是 msggetmsgsnd函数,并且也可以看到,实际存入的数据是经过PHP封装序列化过之后的数据,所以我们存入的命名是4个字节,实际显示的是11个字节的原因,当然,我们也可以在函数中禁用序列化

读进程 demo22.php
代码语言:javascript
复制
//根据一个存在的文件和标识生成消息队列的key
$key = ftok('demo21.php','a');

//创建消息队列
$msgId = msg_get_queue($key);

//接收消息队列消息
msg_receive($msgId,1,$type,1024,$message);


var_dump($message);

执行命令,查看返回结果,可以看到我们写入的数据

再次调用ipcs查看消息队列相关信息,发现数据已被取走并清零

父子进程消息队列通信

假设是子进程接收,父进程发送
代码语言:javascript
复制
$key = ftok('demo23.php','a');

//获取消息队列
$msgId = msg_get_queue($key);

//打印消息队列信息
print_r(msg_stat_queue($msgId));


$pid = pcntl_fork();

$i = 1 ;

//子进程
if(0==$pid)
{
    while (1){
        //接收消息队列信息
        msg_receive($msgId,0,$type,1024,$msg);

        echo $msg."\r\n";
    }

}


while (1){
    //发送队列
    msg_send($msgId,1,'test');
    sleep(3);
     //当发送五次后
    if($i++ ==5)
    {
        //杀死子进程
        posix_kill($pid,SIGKILL);
        break;
    }
}

//回收子进程
$pid = pcntl_wait($status);

//子进程回收成功
if($pid > 0)
{
    fprintf(STDOUT,"child procss exit ok pid=%d\r\n",$pid);
}

//清除消息队列
if(msg_remove_queue($msgId))
{
    fprintf(STDOUT,"queue exit ok\r\n");
}

执行命令,查看结果。可以看到上面打印的是队列的相关信息,如mode 是权限、qnum队列中有几条、qbytes 消息队列的最大限制等等,最终执行五次后,退出子进程并回收

执行pstree -ap 命令查看到是两个进程再执行

再次执行 ipcs 查看,发现只剩我们上面测试的那一个消息队列,本次运行的消息队列已经清除成功

注意
  • 当开启序列化时,如果发送的数据字节,小于接收数据的字节(msg_receive函数的第四个参数),那么数据就会反序列化失败,并抛出系统异常
  • 当序列化时,设置的接收字节小于发送的字节并设置为MSG_NOERROR(msg_receive函数的第七个参数)时,不会抛出系统异常并正常接收设置的字节数,舍弃其他字节数据
  • 当接收数据为非阻塞方式时,设置MSG_IPC_NOWAIT(msg_receive函数的第七个参数),系统会一直调用底层函数并返回失败,造成CPU资源浪费
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Linux进程通信之IPC消息队列
    • 不同进程间消息队列通信
      • 写进程demo21.php
      • 读进程 demo22.php
    • 父子进程消息队列通信
      • 假设是子进程接收,父进程发送
      • 注意
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档