在 Mac OSX 上设置 System V 消息队列大小

Setting System V message queue size on Mac OSX

我目前在 Mac OSX 上使用 System V 消息队列,但无法将队列大小设置为大于 2048 字节的值。这是一个可编译的例子 test.c:

#include <stdio.h>
#include <sys/msg.h>
#include <stdlib.h>

int main() {
  // get a message queue id
  int id = msgget(IPC_PRIVATE,IPC_CREAT|0600);
  if (-1 == id)
      exit(1);

  // get message queue data structure
  struct msqid_ds buf;
  if (-1 == msgctl(id, IPC_STAT, &buf))
      exit(1);
  printf("size is %lu bytes\n", buf.msg_qbytes);

  // set new buffer size
  buf.msg_qbytes = 2750;
  printf("setting size to %lu bytes\n", buf.msg_qbytes);
  if (-1 == msgctl(id, IPC_SET, &buf))
      exit(1);

  // check updated message queue data structure
  if (-1 == msgctl(id, IPC_STAT, &buf))
      exit(1);
  printf("size is %lu bytes\n", buf.msg_qbytes);
}

编译:

clang -Wall -pedantic -o test test.c

和运行与:

sudo ./test

注意:您有 运行 上面的代码 sudo 以确保 msgcntl 调用成功。

这个程序片段的输出是:

size is 2048 bytes
setting size to 2750 bytes
size is 2048 bytes

为什么队列大小没有改变?

编辑: ipcs -Q 的输出显示:

IPC status from <running system> as of Tue Dec  1 10:06:39 PST 2015
msginfo:
    msgmax:  16384  (max characters in a message)
    msgmni:     40  (# of message queues)
    msgmnb:   2048  (max characters in a message queue)
    msgtql:     40  (max # of messages in system)
    msgssz:      8  (size of a message segment)
    msgseg:   2048  (# of message segments in system)

msgmnb可以变大吗,还是我卡住了?

msgctl()

的手册页

代码更改的字段是当前队列中的字节数,而不是队列中的最大字节数。

建议查看:msglen_t msg_qbytes这是队列中允许的最大字节数。

我找不到 Mac 特定的文档,但是 POSIX says 当通过 msgget() 创建消息队列时,它的“msg_qbytes 应该被设置等于系统限制。” msgget() 的 BSD 手册页也是如此,那是 OS X 的最近亲属。对于它的价值,Linux 手册页似乎普遍同意。

这一切都非常一致地表明,如果您的初始队列大小不够大,那么您就会被淘汰。你可以(也许)缩小它,但你不能让它超过它的初始值。

似乎 OS X 不允许增加消息队列的大小。系统 V 实现是旧的,根本没有记录。我还发现奇怪的是 message.h 中缺少定义 MSGMNB、MSGMAX,而您可以在 Linux 和其他 Unix 实现中找到它。

我也找到这个:

OS X is the worst of the lot. Each queue is limited to 2048 bytes and OS X silently ignores attempts to increase this (just like FreeBSD). To add insult to injury, there appears to be no way to increase this limit short of recompiling the kernel. I'm guessing at this based on the Darwin message queue limits. (http://semanchuk.com/philip/sysv_ipc/)

文档于 2014 年 9 月更新,并确认了苹果邮件列表中的post:

http://lists.apple.com/archives/unix-porting/2008/Jan/msg00033.html

@Mark Setchell 在评论中指出。

此外,OS X 不支持最近的 Ruby 包装器实现,作者指出:

The messages are handled by the kernel of your computer. Not all kernels have support for POSIX message queues, a notably example is Darwin (OS X). Darwin implements the older System V IPC API. (https://github.com/Sirupsen/posix-mqueue)

在网络上还有其他来源(大部分是旧的)表明除了重新编译内核之外别无他法来增加消息队列限制。

更新:Apple 的立场是不鼓励使用 System V IPC here

Some System V primitives are supported, but their use is discouraged in favor of POSIX equivalents.

附带建议,补充: msgctl(id, IPC_RMID, NULL); 在测试代​​码的最后,有些人(比如我,叹息!)可能会忘记每个队列都必须关闭。