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 建立訊息佇列。對同一個 key 第二次呼叫 msg_get_queue() 會返回不同的訊息佇列識別碼,但兩個識別碼都會存取相同的底層訊息佇列。

參數

key

訊息佇列數值 ID

permissions

佇列權限。預設為 0666。如果訊息佇列已存在,則會忽略 permissions

回傳值

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

變更日誌

版本 說明
8.0.0 成功時,此函式現在會返回 SysvMessageQueue 實例;先前,會返回 resource

參見

新增註解

使用者貢獻的註解 5 個註解

2
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

您可以使用 "ipcrm" 命令以 root 身分清除訊息佇列。使用 "man ipcrm" 來取得更多資訊。
佇列中最大訊息的預設設定儲存在 /proc/sys/fs/mqueue/msg_max 中。若要將其增加到最多 100 個訊息,只需執行
echo 100 > /proc/sys/fs/mqueue/msg_max

請務必遵循良好的程式設計風格,並在您的指令碼結束前關閉/釋放所有訊息佇列,以避免出現這些警告訊息。
2
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;
}
?>
1
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
1
Joey
5 年前
我發現很難弄清楚如何真正可靠地使用它,特別是在衝突方面。

它對應到 SysV IPC msgget。

依我看,您有三個選項...

1. 自己管理 ID,分配各種範圍或使用某種集中式機制。
2. 使用 ftok。這會嘗試尋找唯一的 ID,但不能保證在所有情況下都是唯一的或恆定的。它依賴使用檔案,從中它會使用 inode 和 dev 中的位元,它預期它們是唯一的。這是標準方法,只要沒有太不尋常的情況,它應該可以正常運作 (但可能無法在徹底的 FS 變更中存活)。
3. 使用 0 作為金鑰,這似乎對應到 IPC_PRIVATE,一個神奇的值,如果作為金鑰提供,每次都會建立一個新的佇列 (實際上沒有金鑰)。

不幸的是,選項 #3 在 PHP 中的用途有限。

在 C 中,這可能很有用,因為佇列資源僅由 int 識別,並且可以傳遞。

在 PHP 中,它的實用性令人質疑,因為只有資源能在單一程序中傳遞。即使它只是一個包裝過的整數,也無法使用 serialize / unserialize 來傳遞資源。

返回的 msqid 也不是完全不可預測的,所以很容易被意外存取。我拿到的第一個值是 0。

如果你像這樣建立一個佇列,你會發現它非常惱人,因為你無法透過 PHP 刪除它。

像所有 IO 操作一樣,值得包裝這個函式,並且在輸入為 0 時拋出例外。
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