PHP Conference Japan 2024

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() 返回一个可用于访问具有给定 key 的 System V 消息队列的 ID。第一次调用使用可选的 permissions 创建消息队列。对相同 keymsg_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 机器上收到此消息

Warning: msg_get_queue() [function.msg-get-queue]: failed for key 0x12345678: No space left on device in /path/to/script.php on line 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" ;

## Create or attach to a message queue
$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 上收到以下消息

Warning: msg_get_queue() [function.msg-get-queue]: failed for key 0x12345678: No space left on device in /path/to/script.php on line 1

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

它映射到 SysV IPC msgget。

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

1. 自己管理 ID,分配各种范围或使用某种集中式机制。
2. 使用 ftok。这尝试查找唯一的 ID,尽管它不能保证在任何情况下都是唯一或恒定的。它依赖于使用文件,从中它使用它期望唯一的文件 inode 和 dev 的位。这是标准方法,只要没有太异常的情况,它应该可以工作(但可能无法在彻底的文件系统更改中幸存)。
3. 使用 0 作为键,它似乎映射到 IPC_PRIVATE,这是一个魔法值,如果作为键提供,则每次都会创建一个新的队列(没有有效的键)。

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

在 C 中,这可能很有用,因为队列资源仅由一个整数标识,并且可以传递。

在 PHP 中,它的实用性值得怀疑,因为只有资源可以在单个进程内传递。即使它只是一个包装的整数,也不可能使用序列化/反序列化传递资源。

返回的 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