Linux消息队列mq_receive返回Message too long且属性未生效问题
问题原因分析
1. 自定义属性未生效的核心原因
POSIX消息队列的mq_open函数传入的struct mq_attr参数,仅当本次调用通过O_CREAT新建队列时才会生效。如果对应名称的消息队列已经存在于系统中,O_CREAT只会打开已有队列,你传入的属性参数会被直接忽略。
Linux系统POSIX消息队列默认的mq_msgsize值就是8192字节,和你输出的结果完全匹配,说明你运行代码前系统中已经存在同名的/sp-example-server队列,直接复用了旧队列的默认属性,你自定义的256字节上限没有生效。
补充说明:POSIX消息队列是内核持久化资源,只要没有手动删除或者重启系统,之前创建的队列会一直保留,不会随程序退出自动销毁。
2. 宏定义的潜在隐患
你定义MSG_BUFFER_SIZE时没有加括号:
// 原写法有运算优先级隐患 #define MSG_BUFFER_SIZE MAX_MSG_SIZE + 10
虽然当前定义数组时计算的长度是对的(256+10=266字节),但如果后续代码中出现MSG_BUFFER_SIZE * 2这类运算,会被展开为256 + 10 * 2 = 276,和预期的266*2=532不符,建议修改为:
#define MSG_BUFFER_SIZE (MAX_MSG_SIZE + 10)
3. Message too long错误的直接原因
你当前队列实际的mq_msgsize是8192字节,但接收缓冲区in_buffer只有266字节,小于要求的最小值,不符合mq_receive的参数要求:POSIX规范要求mq_receive的第三个参数(缓冲区长度)必须大于等于队列的mq_msgsize属性,无论实际接收的消息长度是多少。
解决方案
- 先删除系统中已存在的同名旧队列:
可以直接执行命令rm /dev/mqueue/sp-example-server,也可以在代码中mq_open之前先调用mq_unlink("/sp-example-server");删除旧队列,再重新创建就能生效你自定义的属性。 - 如果不需要修改队列属性,可以直接把接收缓冲区的长度调整为不小于队列实际的
mq_msgsize值(当前场景开8192字节以上的缓冲区即可)。
内容的提问来源于stack exchange,提问作者xyf
相关产品推荐
相关产品推荐

