PHP 进程间通信——消息队列(msg_queue)

时间:2023-01-18 22:35:08

Untitled

PHP 进程间通信——消息队列

本文不涉及PHP基础库安装。详细安装说明,请参考官网,或期待后续博客分享。

1、消息队列函数准备

<?php
//生成一个消息队列的key
$msg_key = ftok(__FILE__, 'a');
//产生一个消息队列
$msg_queue = msg_get_queue($msg_key, 0666);
//检测一个队列是否存在 ,返回boolean值
$status = msg_queue_exists($msg_key);
//可以查看当前队列的一些详细信息
$message_queue_status = msg_stat_queue($msg_queue);

//将一条消息加入消息队列
msg_send($msg_queue, 1, "Hello, 1");
msg_send($msg_queue, 1, 'Hello, 2');
msg_send($msg_queue, 1, "Hello, 3");

//从消息队列中读取一条消息。
msg_receive($msg_queue, 1, $message_type, 1024, $message1);
msg_receive($msg_queue, 1, $message_type, 1024, $message2);
msg_receive($msg_queue, 1, $message_type, 1024, $message3);

//移除消息队列
msg_remove_queue($msg_queue);
echo $message1.PHP_EOL;
echo $message2.PHP_EOL;
echo $message3.PHP_EOL;

/**
* msg_send 有三个必选参数
* resource $queue ,
* int $msgtype ,
* mixed $message
*
* 第一个必须要是队列资源类型。resource(4) of type (sysvmsg queue)
* 第二个参数是消息类型,一个整形,且必须大于0.
* msg_send() sends a message of type msgtype (which MUST be greater than 0) to the message queue specified by queue.
* 第三个参数。是要发送的信息。可以是字符串,也可以是数组。默认会被serialize.
*/

/**
* msg_receive 的参数比较多。必须要填的参数有5个。
* resource $queue ,
* int $desiredmsgtype ,
* int &$msgtype ,
* int $maxsize ,
* mixed &$message
*
* 其中$desiredmsgtype .经过测试和官网描述不符,暂不解释。
*
* $msgtype 。这个是msg_send 中所选定的msg_type.这是一个引用参数。
* The type of the message that was received will be stored in this parameter.
*
* $maxsize。
* The maximum size of message to be accepted is specified by the maxsize;
* if the message in the queue is larger than this size the function will fail (unless you set flags as described below).
* 这个参数声明的是一个最大的消息大小,如果超过则会报错。
*
* $message.
* 上文msg_send 发送的消息类型。
*/

2、多进程通信实例

<?php
/**
* 这段代码模拟了一个日常的任务。
* 第一个父进程产生了一个子进程。子进程又作为父进程,产生10个子进程。
* 可以简化为A -> B -> c,d,e... 等进程。
* 作为A来说,只需要生产任务,然后交给B 来处理。B 则会将任务分配给10个子进程来进行处理。
*
*/

//设定脚本永不超时
set_time_limit(0);
$ftok = ftok(__FILE__, 'a');
$msg_queue = msg_get_queue($ftok);
$pidarr = [];

//产生子进程
$pid = pcntl_fork();
if ($pid) {
//父进程模拟生成一个特大的数组。
$arr = range(1,100000);

//将任务放进队里,让多个子进程并行处理
foreach ($arr as $val) {
$status = msg_send($msg_queue,1, $val);
usleep(1000);
}
$pidarr[] = $pid;
msg_remove_queue($msg_queue);
} else {
//子进程收到任务后,fork10个子进程来处理任务。
for ($i =0; $i<10; $i++) {
$childpid = pcntl_fork();
if ($childpid) {
$pidarr[] = $childpid; //收集子进程processid
} else {
while (true) {
msg_receive($msg_queue, 0, $msg_type, 1024, $message);
if (!$message) exit(0);
echo $message.PHP_EOL;
usleep(1000);
}
}
}
}

//防止主进程先于子进程退出,形成僵尸进程
while (count($pidarr) > 0) {
foreach ($pidarr as $key => $pid) {
$status = pcntl_waitpid($pid, $status);
if ($status == -1 || $status > 0) {
unset($pidarr[$key]);
}
}
sleep(1);
}
?>

以上的示例只是为了说明多进程通信的应用示例,并未在真实的项目中应用。为了示例方便,省略了很多的校验条件。但作为了解过程及原理来说,并不影响。

在执行while 循环时候,必须要使用usleep(1000) 以上。否则CPU可能会被撑爆。

以上的多进程通信,没有产生僵尸进程。得益于最后一段的while循环。

其原理在于,父进程在每次循环的时候都检测子进程是否退出。如果退出,则父进程就会回收该子进程。并且将该进程从进程列表中删除。

可以使用ps aux |grep process.php来查看当前产生的进程数量。 其中process.php 是运行的文件名

效果如下:

[root@roverliang~]# ps aux |grep php
74:root 4163 9.3 2.2 243908 22844 pts/1 S+ 17:42 0:00 php process.php
75:root 4164 0.0 0.3 229104 3924 pts/1 S+ 17:42 0:00 php process.php
76:root 4165 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
77:root 4166 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
78:root 4167 1.0 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
79:root 4168 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
80:root 4169 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
81:root 4170 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
82:root 4171 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
83:root 4172 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
84:root 4173 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php
85:root 4174 1.3 0.4 229104 4124 pts/1 S+ 17:42 0:00 php process.php

有疑问的话,可以共同讨论学习。博主也是刚学习这块,如果有什么不对的,希望能得到指点,共同提高。

PHP 进程间通信——消息队列(msg_queue)的更多相关文章

  1. Linux进程间通信-消息队列(mqueue)

    前面两篇文章分解介绍了匿名管道和命名管道方式的进程间通信,本文将介绍Linux消息队列(posix)的通信机制和特点. 1.消息队列 消息队列的实现分为两种,一种为System V的消息队列,一种是P ...

  2. Linux下进程间通信--消息队列

    消息队列的定义遍地都是,不想移驾,请看下文: 一.定义: 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认 为是有一个类型,接收者进程接收的数据块可以有不同的类型值.我 ...

  3. 详解linux进程间通信-消息队列

    前言:前面讨论了信号.管道的进程间通信方式,接下来将讨论消息队列. 一.系统V IPC 三种系统V IPC:消息队列.信号量以及共享内存(共享存储器)之间有很多相似之处. 每个内核中的 I P C结构 ...

  4. Linux进程间通信—消息队列

    四.消息队列(Message Queue) 消息队列就是消息的一个链表,它允许一个或者多个进程向它写消息,一个或多个进程向它读消息.Linux维护了一个消息队列向量表:msgque,来表示系统中所有的 ...

  5. Linux 进程间通信 消息队列 实现两个进程间通信

    例子: 通过消息队列实现两个进程间通信,一个进程从终端输入数据,通过消息队列发送,另一个进程通过消息队列接收数据 文件1 创建进程1 终端输入通过消息队列发送数据 #include <stdio ...

  6. 进程间通信消息队列msgsnd执行:Invlid argument——万恶的经验主义

    最近在搞进程间通信,首先在我的ubuntu 14.04上写了接口和测试demo,编译和执行都OK,,代码如下: 接口文件ipcmsg.h /* ipcmsg.h */ #ifndef H_MSGIPC ...

  7. linux进程间通信-消息队列

    一 消息队列的介绍 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构. 我们可以通过发送消息来避免命名管道的 ...

  8. IPC进程间通信---消息队列

    消息队列 消息队列:消息队列是一个存放在内核中的消息链表,每个消息队列由消息队列标识符标识.与管道不同的是消息队 列存放在内核中,只有在内核重启(即操作系统重启)或者显式地删除一个消息队列时,该消息队 ...

  9. linux进程间通信消息队列:msgsnd&colon; Invalid argument

    今天写了个消息队列的小测试程序结果send端程序总是出现:msgsnd: Invalid argument,搞了半个小时也没搞明白,后来查资料发现我将(st_msg_buf.msg_type = 0; ...

随机推荐

  1. Restful WebApi项目开发实践

    前言 踩过了一段时间的坑,现总结一下,与大家分享,愿与大家一起讨论. Restful WebApi特点 WebApi相较于Asp.Net MVC/WebForm开发的特点就是前后端完全分离,后端使用W ...

  2. React&period;render和reactDom&period;render的区别

    刚开始学习react.js.发现网上的资料,有些是写着react.render,有些写着reactDom.render.觉得很奇怪就查阅了一下资料.解释如下: 这个是react最新版api,也就是0. ...

  3. 采用CAS原理构建单点登录

    企业的信息化过程是一个循序渐进的过程,在企业各个业务网站逐步建设的过程中,根据各种业务信息水平的需要构建了相应的应用系统,由于这些应用系统一般是在不同的时期开发完成的,各应用系统由于功能侧重.设计方法 ...

  4. Java中的自增问题(i&equals;i&plus;&plus;)

    也许我这是在较真, 但是我们确实有时候就不小心就错写为这种情况了. 看如下代码: public class Test{ public static void main(String[] args){ ...

  5. mysql主从复制 转

    mysql服务器的主从配置,这样可以实现读写分离,也可以在主库挂掉后从备用库中恢复.需要两台机器,安装mysql,两台机器要在相通的局域网内,可以分布在不同的服务器上,也可以在一台服务器上启动多个服务 ...

  6. MVC开发Markdown编辑器(2)

    MVC开发Markdown编辑器(2) MVC Markdown 实时预览 我希望实现一个在线实时预览的Markdown编辑器,左边是编辑处,右边是实时预览界面. 准备工作 引入相关js和css 这里 ...

  7. python网络编程——将IPv4地址转换成不同的格式

    1.将IPv4地址转换为32位二进制格式,用做底层网络函数. import socket from binascii import hexlify def convert_IPv4_address() ...

  8. 用yum安装JDK&lpar;CentOS&rpar;

    1.查看yum库中都有哪些jdk版本 [root@localhost ~]# yum search java|grep jdk 2.选择版本,进行安装 [root@localhost ~]# yum  ...

  9. Basic berkeley socket functions

    gethostbyname() DNS を通して.Domain の Information を GET する.例えば IP Address なんだ. げん型: #include <netdb.h ...

  10. 黄聪:JQUERY判断操作CHECKBOX选中、取消选中、反选、第二次无法选中的问题

    用JQuery做CheckBox全选和反选的时候,遇到一个问题.当用JQ控制全选,全取消一次以后,再次点击全选,发现代码变了,但是CheckBox没有处于选中状态. $("#id" ...