msg_get_queue

(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)

msg_get_queue创建或附加到消息队列

描述

msg_get_queue(int $key, int $permissions = 0666): SysvMessageQueue|false

msg_get_queue() 返回一个 ID,该 ID 可用于访问具有给定 key 的 System V 消息队列。第一次调用将使用可选的 permissions 创建消息队列。对同一个 key 的第二次调用 msg_get_queue() 将返回一个不同的消息队列标识符,但这两个标识符都访问同一个底层消息队列。

参数

key

消息队列数字 ID

permissions

队列权限。默认为 0666。如果消息队列已存在,则将忽略 permissions

返回值

返回 SysvMessageQueue 实例,该实例可用于访问 System V 消息队列,或在失败时返回 false

变更日志

版本 描述
8.0.0 成功时,此函数现在返回一个 SysvMessageQueue 实例;以前,返回的是一个 resource

参见

添加备注

用户贡献的备注 5 个备注

david dot schueler at tel-billig dot de
15 年前
如果您在 *NIX 盒子上收到此消息

警告:msg_get_queue() [function.msg-get-queue]:对于密钥 0x12345678 失败:/path/to/script.php 第 1 行的设备空间不足

您可以使用 root 身份运行 "ipcrm" 命令来清除消息队列。使用 "man ipcrm" 获取有关它的更多信息。
队列中最大消息的默认设置存储在 /proc/sys/fs/mqueue/msg_max 中。要将其增加到最大 100 条消息,只需运行
echo 100 > /proc/sys/fs/mqueue/msg_max

请确保遵循良好的编程风格,并在脚本退出之前关闭/释放所有消息队列,以避免这些警告消息。
pail dot luo at gmail dot com
15 年前
一个简单的示例来介绍消息队列。

<?php
if ( sizeof($argv)<2 ) {
echo
"Usage: $argv[0] stat|send|receive|remove msgType MSG [msg] \n\n" ;
echo
" EX: $argv[0] send 1 \"This is no 1\" \n" ;
echo
" $argv[0] receive ID \n" ;
echo
" $argv[0] stat \n" ;
echo
" $argv[0] remove \n" ;
exit;
}

$MSGKey = "123456" ;

## 创建或附加到消息队列
$seg = msg_get_queue($MSGKey) ;

switch (
$argv[1] ) {
case
"send":
msg_send($seg, $argv[2], $argv[3]);
echo
"msg_send done...\n" ;
break;

case
"receive":
$stat = msg_stat_queue( $seg );
echo
'Messages in the queue: '.$stat['msg_qnum']."\n";
if (
$stat['msg_qnum']>0 ) {
msg_receive($seg, $argv[2], $msgtype, 1024, $data);
var_dump($msgtype);
var_dump($data);
echo
"\n";
}
else {
echo
"No Msg...\n";
}
break;

case
"stat":
print_r( msg_stat_queue($seg) );
break;

case
"remove":
msg_remove_queue($seg);
break;
}
?>
Michael Iatrou
14 年前
如果您收到以下消息(在 Linux 上)

警告:msg_get_queue() [function.msg-get-queue]:对于密钥 0x12345678 失败:/path/to/script.php 第 1 行的设备空间不足

除了 [其他人已] 建议的之外,您还应该检查并为内核参数 kernel.msgmni 设置适当的值,例如 sysctl -w kernel.msgmni=256
Joey
5 年前
我发现很难弄清楚如何真正可靠地使用它,尤其是在碰撞方面。

它映射到 SysV IPC msgget。

据我所知,您有三种选择...

1. 自己管理 ID,分配各种范围或使用某种集中机制。
2. 使用 ftok。它尝试找到一个唯一的 ID,尽管不能保证在绝对所有情况下都是唯一的或不变的。它依赖于使用文件,从中使用它期望唯一的 inode 和 dev 的位。这是标准方法,只要没有太不寻常的情况,它应该可以工作(但可能无法在彻底的 FS 更改后存活)。
3. 使用 0 作为密钥,这似乎映射到 IPC_PRIVATE,一个神奇的值,如果提供它作为密钥,则每次都会创建一个新队列(实际上没有密钥)。

不幸的是,选项 #3 在 PHP 中用途有限。

在 C 中,这很有用,因为队列资源只是通过 int 标识,并且可以在各个进程之间传递。

在 PHP 中,它的效用值得怀疑,因为只有资源可以在单个进程内传递。即使它只是一个包装的 int,也不可能使用 serialize / unserialize 来传递资源。

返回的 msqid 并不完全是不可预测的,因此很容易被意外访问。我得到的第一個是 0。

如果您像这样创建队列,您会发现它非常烦人,因为无法通过 PHP 删除它。

与所有 IO 一样,值得包装此函数并在输入为 0 时引发异常。
martin dot velek at gmail dot com
17 年前
缺乏 IPC_EXCL 使我感到不高兴。当然,您可以使用 ftok() 生成唯一的密钥。此代码并非万能,同一用户下的另一个进程可以打开队列,并且函数返回 true。但在某些情况下它可能会有所帮助。

代码

<?
function ipcEXCL($res,$perm)
{
$pole = msg_stat_queue($res);

if($pole['msg_perm.uid']==posix_getuid() &&
$pole['msg_perm.gid']==posix_getgid() &&
$pole['msg_perm.mode']==$perm &&
$pole['msg_stime']==0 &&
$pole['msg_rtime']==0 &&
$pole['msg_qnum']==0 &&
$pole['msg_lspid']==0 &&
$pole['msg_rspid']==0)
return true;
else
return false;
}

$res=msg_get_queue($key,$perm);

if(ipcEXCL($res,$perm))
echo "可能我是创建者:";
else
echo "可能不是";
?>
To Top