POSIX C消息队列IPC示例异常:无效key可用,有效key失效
问题分析与解答
先明确两个核心点:
ftok返回-1仅代表生成唯一IPC key失败,但-1本身是合法的IPC key值,完全可以用于msgget调用。- 消息队列的共享逻辑是:只要两个进程使用相同的key值,且
msgget参数匹配,就能访问同一个队列——和这个key是ftok生成的还是硬编码的无关。
逐个拆解你的测试现象:
无dummy.txt时ftok报错但通信正常
当dummy.txt不存在时,ftok调用失败返回-1。如果你的代码没有在ftok失败时终止执行,而是继续用-1作为key调用msgget,那么读写进程都会以key=-1去创建/获取队列。只要msgget的权限参数(比如IPC_CREAT | 0666)一致,两个进程会拿到同一个消息队列ID,自然能正常收发消息。创建dummy.txt后ftok正常但读进程挂起
这时候ftok生成了有效的key,但问题大概率出在代码细节上:- 读写进程的
ftok项目ID(第二个参数)不一致:比如bar.c用ftok("dummy.txt", 1),foo.c用ftok("dummy.txt", 2),这会生成完全不同的key,导致两个进程访问的是独立的消息队列——写进程把消息发到自己的队列,读进程在另一个空队列里等待,必然挂起。 msgrcv的消息类型参数不匹配:比如写进程发送的消息类型是1,但读进程msgrcv的msgtyp设为2,读进程会一直等待类型为2的消息,而队列里只有类型1的,所以卡住。- 写进程的
msgsnd调用失败:比如权限不足、队列满等,导致消息根本没写入队列,读进程自然空等。
- 读写进程的
ftok传nullptr且用不同ID,报错但通信正常
和第一个现象本质相同:ftok传入nullptr会失败返回-1,读写进程最终都用key=-1调用msgget,只要参数一致,就能拿到同一个队列,所以通信不受影响。不同的项目ID在这里没用,因为ftok已经失败了,最终用的都是-1这个key。
核心结论
你混淆了「ftok生成失败」和「key值合法性」的概念:-1不是无效key,只是ftok生成失败的返回值;而ftok生成的有效key如果在读写进程中不统一,反而会导致访问不同队列,出现读进程挂起的情况。
内容的提问来源于stack exchange,提问作者Cosmo
相关产品推荐
相关产品推荐

