尝试使用 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。查看ulimit
和 limits.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 消息队列创建消息队列时权限被拒绝的主要内容,如果未能解决你的问题,请参考以下文章