首先消息队列是存放消息的队列,而队列则是一种先进先出的数据结构。
在PHP扩展中,封装了8个消息队列相关的函数,有 ftok
、msg_get_queue
、msg_queue_exists
、msg_receive
、msg_remove_queue
、msg_send
、msg_set_queue
、msg_stat_queue
具体的相关参数以及介绍,请查看PHP手册及相关文档 PHP手册之IPC
//根据一个存在的文件和标识生成消息队列的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
命令查看一下
通过执行上面的命令,我们可以看到,实际底层当中调用的是 msgget
、msgsnd
函数,并且也可以看到,实际存入的数据是经过PHP封装序列化过之后的数据,所以我们存入的命名是4个字节,实际显示的是11个字节的原因,当然,我们也可以在函数中禁用序列化
//根据一个存在的文件和标识生成消息队列的key
$key = ftok('demo21.php','a');
//创建消息队列
$msgId = msg_get_queue($key);
//接收消息队列消息
msg_receive($msgId,1,$type,1024,$message);
var_dump($message);
执行命令,查看返回结果,可以看到我们写入的数据
再次调用ipcs
查看消息队列相关信息,发现数据已被取走并清零
$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
查看,发现只剩我们上面测试的那一个消息队列,本次运行的消息队列已经清除成功