尝试使用 POSIX 消息队列创建消息队列时权限被拒绝

Posted

技术标签:

【中文标题】尝试使用 POSIX 消息队列创建消息队列时权限被拒绝【英文标题】:Permission denied when trying to create message queue using POSIX Message Queues 【发布时间】:2019-10-20 21:26:22 【问题描述】:

我正在通过关注The Linux Programming Interface 创建一个具有以下 sn-p 的消息队列。

if((mq_open("/my_message_queue", O_CREAT, O_RDWR, NULL)) == -1) 
    perror("mq creation failed");

运行这个 sn-p 我得到一个错误:“权限被拒绝”。我想检查一下我之前是否创建了队列并且没有销毁它,所以我使用了 ipcs。但是,ipcs 不显示任何活动的消息队列。我以前从未在我的开发环境中使用过 POSIX IPC 库(Ubuntu 18.04)。我必须进行一些设置以允许我的用户进程创建消息队列吗?我是否错误地使用了 API?

【问题讨论】:

您的 msgqueue 限制可能设置为 0。查看 ulimitlimits.conf 尝试从终端运行ulimit -q,看看它会输出什么。 ulimit -q 返回 819200 哦! "/my_message_queue"。您正在尝试在根目录中创建一个 msgqueue,您不应该对其具有写权限。 @ChristianGibbons POSIX 消息队列 (mq_open()) 名称允许以 / 开头,/ 字符的任何其他使用是实现定义的。假设 Linux,在传递给 mq_open() 的名称中只允许使用前导 / 字符。 【参考方案1】:

来自the man page:

oflag 参数指定控制调用操作的标志。 (标志值的定义可以通过包含<fcntl.h>获得。)在oflag中必须指定以下内容之一:

O_RDONLY 打开队列仅接收消息。

O_WRONLY 打开队列仅发送消息。

O_RDWR 打开队列以发送和接收消息。

您的代码中没有这三个值。或者更确切地说,您这样做了,但它在 mode 参数中,而不是 oflag 参数中,其中相应的数字具有完全不同的含义。第三个参数是创建队列时使用的文件系统权限位(就像创建新文件时 open() 的第三个参数一样),而不是打开队列的模式。

【讨论】:

但请注意O_RDONLY 定义为0。 (但我认为这唯一正确的答案) @o12c 这是一个不应该依赖的实现细节。我很确定这些宏的实际值不是由相关标准设置的。【参考方案2】:

EACCES:队列存在,但调用者没有权限 以指定的模式打开。

ipcs 不会向您显示您无法读取的队列。它没有向您显示队列与返回权限错误的 mq_open 一致。

TLPI 将 mount -t mqueue 描述到您选择的目录。然后,您可以在该目录上使用 ls(1) 来查看队列,甚至可以通过读取该目录中的“文件”来询问队列的状态。

我的猜测是队列存在并且属于root....

【讨论】:

能否通过其他方式查看属于root的队列?我在第 52 章中没有看到 mount -t mqueue,也许我错过了。 你是对的,队列存在并且属于root。它在 /dev/mqueue 下,但不显示在 ipcs 下【参考方案3】:

POSIX states :

... name 参数符合路径名的构造规则,除了 name 中除前导 <slash> 字符之外的 <slash> 字符的解释是实现定义的...

在 Linux 上,名称 /my/message_queue 不正确。 Linux 要求名称以 / 开头,但不能包含其他 / 字符。

根据Linux mq_overview.7 man page:

使用mq_open(3) 创建和打开消息队列;这个函数 返回一个消息队列描述符(mqd_t),用于引用 在以后的调用中打开消息队列。每个消息队列是 由/somename 形式的名称标识;也就是说,一个空- 由最多 NAME_MAX(即 255)个字符组成的终止字符串 一个初始斜线,后跟一个或多个字符,none of 是斜线。

【讨论】:

我的名字是“/my_message_queue”,我认为它遵循命名规则。

以上是关于尝试使用 POSIX 消息队列创建消息队列时权限被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

POSIX 消息队列的替代方案

Posix消息队列

Posix消息队列

使用 POSIX 消息队列进行进程内通信

如何创建 POSIX 共享消息队列而不将其创建为仅作为 root 访问?

POSIX 消息队列 - 打开时出错:参数无效