消息队列Linux发送信息出错,消息队列创建失败问题

本文探讨了在Linux系统中遇到的消息队列创建失败,特别是EACCESS权限错误的问题。作者分析了msgget()系统调用的返回值,并通过ftok()函数的原理,发现可能是由于文件的索引节点号和子序号导致的key冲突。解决方案包括删除并重新创建目录,以及使用随机ID避免冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*************************************************************************/

系统调用:msgget();

原型:intmsgget(key_t

key,int msgflg);

返回值:如果成功,返回消息队列标识符

如果失败,则返回-1:

errno=EACCESS(权限不允许)

EEXIST(队列已经存在,无法创建)

EIDRM(队列标志为删除)

ENOENT(队列不存在)

ENOMEM(创建队列时内存不够)

ENOSPC(超出最大队列限制)

/*************************************************************************/

发现应该是EACCESS错误,msgget包括创建或得到消息队列的功能,得到消息队列是得到key对应的队列ID,报无权限,有可能系统上有重复的非本用户下的队列,造成无权访问的问题。按照这个思路,我加了打印语句(不好的调试方式:>),输出了由ftok创建的key为:16941057,转成16进制得到:0x01028001,然后用linux下查看消息队列的命令:

ipcs -q|grep 8001 果然得到另外一个用户下的消息队列,现在问题转成了为什么key会重复问题,可以是如何根据目录生成的那?

查阅了资料发现:ftok 的原型声明为:

key_t

ftok( char * fname, int id )

其中,fname是指定的文件名(包括目录名),这个必须是存在,而且是有权限访问的,

id是子序号,虽然为int,但是只有8个比特被使用(0-255)。

”在一般的UNIX实现中,是将文件的索引节点号取出,前面加上子序号得到key_t的返回值。如指定文件的索引节点号为65538,换算成16进制为0x010002,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。

查询文件索引节点号的方法是: ls -i

通过ls -i查询得到我创建key的目录为索引节点为:11370497

转成16进制为AD 8001在linux中取后四位即后面2个字节,我们程序传入的ID为:01 ,不过linux和dev有关系,拼接上ID 最终得到的Key为:0x 01 02 8001 ,dev的查看方法为cat /proc/devices 查看硬盘对应的dev为02 (我自己的理解),得到的值果然重复,用man ftok查看了下:

Typically, a best effort

attempt com-bines the given proj_id byte, the lower 16 bits of the i-node

number, and the lower 8 bits of the device numberinto

a  32-bit  result.

并且有,有时候重复是难免的,既然重复难以避免的怎么办那?对于我的情况,我想可以通过删除创建key的目录,然后重建,不过在这两个动作之间一定要有创建文件的操作,防止再次创建目录的inode节点和原来是同一个,程序代码嘛,可以改成一直随机id的值,直到不报错位置(也许您又更好的办法:>).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值