php多进程通信,有各种各样的方法(进程信号,消息队列,管道,共享内存,socket等等)
本文主要讲php利用linux 消息队列的通信方法
注意:多进程系列文章,都建立在linux环境,php-cli运行模式下
一:消息队列通信介绍
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
消息队列的最佳定义是:内核地址空间中的内部链表。消息可以顺序地发送到队列中,并以几种不同的方式从队列中获取。当然,每个消息队列都是由 IPC标识符所唯一标识的。
二:php消息队列扩展
php如果要使用linux的消息队列,需要安装sysvmsg扩展,官方文档地址:http://php.net/manual/zh/book.sem.php
三:php使用消息队列
1:获取一个IPC标识符ftok();
ftok,可将项目路径与文件标识转换成一个IPC标识符,该标识符可用于创建消息队列
2:获取/创建一个消息队列msg_get_queue()
使用linux命令ipcs -q 可查看系统当前的消息队列数
3:插入数据到队列msg_send()
msg_send (
resource $queue(消息队列资源句柄) ,
int $msgtype(插入数据的类型,用来标识该队列自己的消息类型,自己自定义,必须大于0) ,
mixed $message(插入的数据,可以为数组,下一个参数可以序列化数据)
[, bool $serialize = TRUE(是否序列化数据,默认是)
[, bool $blocking = TRUE (如果消息太大而无法放入队列(linux消息队列限制),则脚本将等待另一个进程从队列中读取消息,并释放足够的空间以发送消息。这被称为阻塞; 您可以通过设置可选blocking参数来防止阻塞FALSE,在这种情况下,如果消息对于队列来说太大,msg_send()将立即返回,并将可选参数FALSE设置 errorcode为MSG_EAGAIN,表示您应稍后尝试再次发送消息。)
[, int &$errorcode ]]] (错误标识));
插入成功之后,ipcs可看到message多了一条:
4:取出一条数据msg_receive
msg_receive (
resource $queue , (消息队列资源句柄)
int $desiredmsgtype (要取出的消息队列类型,如果为0,则不筛选类型,直接返回最先插入的那条,大于0,则筛选类型,返回最先插入的类型数据,小于0,则返回小于等于绝对值的数据,如果消息队列暂无满足要求的数据,则阻塞或者返回false,由flag参数配置),
int &$msgtype (当取出数据时,该变量会赋值为该数据的类型),
int $maxsize (消息的最大大小被指定的被接受 maxsize; 如果队列中的消息大于此大小,则该功能将失败(除非flags按照以下说明设置 )该参数较迷,没有理解),
mixed &$message (当取出数据时,该变量会赋值为该数据)
[, bool $unserialize = TRUE(是否反序列化数据)
[, int $flags = 0
该选项flags
允许您将标志传递给低级msgrcv系统调用。它默认为0,但您可以指定一个或多个以下值(通过将它们相加或相加)。
msg_receive的标志值
MSG_IPC_NOWAIT |
如果没有消息 desiredmsgtype ,立即返回,不要等待。该函数将失败并返回对应的整数值MSG_ENOMSG 。 |
MSG_EXCEPT |
将此标志与desiredmsgtype 大于0 结合使用 会导致函数接收到不等于的第一条消息 desiredmsgtype 。 |
MSG_NOERROR |
如果消息长于maxsize ,则设置此标志将截断消息, maxsize 并且不会发出错误信号。 |
[, int &$errorcode ]]] )如果该函数失败,errorcode
则可选项将被设置为系统errno变量的值。
5:删除队列msg_remove_queue ( resource $queue )
顾名思义,该函数可删除一个消息队列