Linux POSIX消息队列报‘Message Too Long’错误求助
问题分析与修复方案
核心错误原因
你遇到的Message too long错误,本质是消息队列的默认最大消息长度小于你发送的单条消息大小。调用mq_open时传入NULL作为属性参数,会使用系统默认的消息队列配置,而默认的mq_msgsize(单条消息最大字节数)通常不足以容纳M * sizeof(int64_t)大小的消息,导致接收时缓冲区不匹配。
具体修复步骤
1. 显式设置消息队列属性
在创建消息队列前,定义并初始化struct mq_attr结构体,指定足够大的mq_msgsize(等于你发送的最大消息字节数,即M * sizeof(int64_t)),同时设置合理的mq_maxmsg(队列最多容纳的消息数,比如10)。
修改mq_open部分的代码:
int main() { mqd_t mq; struct mq_attr attr; attr.mq_flags = 0; attr.mq_maxmsg = 10; // 根据需求调整,比如允许队列最多存10条消息 attr.mq_msgsize = M * sizeof(int64_t); // 单条消息最大字节数,匹配发送的消息大小 attr.mq_curmsgs = 0; mq = mq_open(MQ_NAME, O_RDWR | O_CREAT, 0666, &attr); if (mq == (mqd_t) - 1) { perror("Cannot create msg queue"); exit(EXIT_FAILURE); } // ... 后续代码不变 }
2. 修复父进程接收逻辑的bug
当前父进程接收时遍历整个M数组并判断message[i] != 0,存在两个问题:
- 未初始化的数组元素可能不是0,导致错误输出垃圾值
- 无法准确处理最后一条不足
M个元素的消息
应该用mq_receive的返回值(实际接收的字节数)来计算有效元素的数量:
// Read from the message queue and write to the output file int64_t message[M]; ssize_t recv_bytes; while ((recv_bytes = mq_receive(mq, (char *) message, M * sizeof(int64_t), NULL)) != -1) { int count = recv_bytes / sizeof(int64_t); for (int i = 0; i < count; i++) { fprintf(output_file, "%" PRId64 "\n", message[i]); } }
3. 修复子进程消息填充的逻辑bug
子进程中curr_msg_size += 1的位置错误,会导致消息内容错位:当消息满了发送后重置为0,后续的质数会被放到message[1]而非message[0]。调整代码顺序:
if (isPrime(number)) { message[curr_msg_size] = number; curr_msg_size += 1; // 先自增,再判断是否满 if (curr_msg_size == M) { // 消息已满 int res = mq_send(mq, (const char *) message, curr_msg_size * sizeof(int64_t), 0); if (res == -1) { perror("mq_send failed on full message"); exit(EXIT_FAILURE); } curr_msg_size = 0; } }
额外注意事项
- 确保
M * sizeof(int64_t)不超过系统允许的消息队列最大消息大小,可以通过/proc/sys/fs/mqueue/msgsize_max查看系统上限 - 若系统默认上限不足,可通过修改该文件(需root权限)调整
内容的提问来源于stack exchange,提问作者DenizTuna
相关产品推荐
相关产品推荐

