分类: LINUX
2011-04-23 16:01:38
/*************************************************************************/
系统调用: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 number into a 32-bit result.
并且有,有时候重复是难免的,既然重复难以避免的怎么办那?对于我的情况,我想可以通过删除创建key的目录,然后重建,不过在这两个动作之间一定要有创建文件的操作,防止再次创建目录的inode节点和原来是同一个,程序代码嘛,可以改成一直随机id的值,直到不报错位置(也许您又更好的办法:>).