C语言消息队列仅能读取type为0的消息问题求助
问题分析与修复方案
核心问题1:消息类型字段不符合System V消息队列规范
System V消息队列要求消息结构体的第一个成员必须是**long int**类型,用于标识消息类型。你当前使用int类型作为tipo,在64位系统下,int(32位)与long int(64位)长度不匹配,会导致内核错误解析消息类型:发送时的int类型tipo被当作long int存储,接收时传入的int类型tipo无法匹配存储的消息类型,因此只能用0(接收任意类型)获取消息。
修复:修改结构体与相关参数类型
将结构体及函数参数中的tipo类型改为long int:
typedef struct mymsgbuf { long int tipo; // 替换原int类型 char testo[MAX_LINE_LENGTH]; } my_msg_buf;
同步修改函数参数:
sendMessage第二个参数改为long int tiporeceiveMessage第二个参数改为long int tipo
核心问题2:消息长度参数的隐性风险
虽然你传入的MAX_LINE_LENGTH是正确的消息正文长度,但建议显式使用sizeof(msgBuf.testo)传递,避免宏定义变更引发错误:
msgsnd调用修改为:msgsnd(msgQId, (void *)&msgBuf, sizeof(msgBuf.testo), 0)msgrcv调用修改为:msgrcv(msgQId, (void *)&msgBuf, sizeof(msgBuf.testo), tipo, IPC_NOWAIT)
附加问题:字符串未终止
strncpy不会自动添加字符串终止符'\0',若传入的msg长度等于MAX_LINE_LENGTH-1,msgBuf.testo会缺少终止符,导致后续strdup和printf出现未定义行为。修复方式:
strncpy(msgBuf.testo, msg, MAX_LINE_LENGTH-1); msgBuf.testo[MAX_LINE_LENGTH-1] = '\0'; // 手动添加终止符
修复后的完整代码示例
结构体定义
#define MAX_LINE_LENGTH 256 typedef struct mymsgbuf { long int tipo; char testo[MAX_LINE_LENGTH]; } my_msg_buf;
发送函数
#include <string.h> #include <stdio.h> #include <errno.h> #include <sys/msg.h> int sendMessage(int msgQId, long int tipo, char *msg) { my_msg_buf msgBuf; msgBuf.tipo = tipo; strncpy(msgBuf.testo, msg, MAX_LINE_LENGTH-1); msgBuf.testo[MAX_LINE_LENGTH-1] = '\0'; if (msgsnd(msgQId, (void *)&msgBuf, sizeof(msgBuf.testo), 0) == -1) { fprintf(stderr, "Error sending message: %s\n", strerror(errno)); return -1; } char *str = receiveMessage(msgQId, tipo); if (str != NULL) { printf("Mess: %s\n", str); free(str); // 释放strdup分配的内存,避免泄漏 } else { printf("No matching message received\n"); } printf("Message sent\n"); return 0; }
接收函数
#include <string.h> #include <stdio.h> #include <errno.h> #include <sys/msg.h> char *receiveMessage(int msgQId, long int tipo) { my_msg_buf msgBuf; if (msgrcv(msgQId, (void *)&msgBuf, sizeof(msgBuf.testo), tipo, IPC_NOWAIT) == -1) { if (errno != ENOMSG) { fprintf(stderr, "Error: %s\n", strerror(errno)); } return NULL; } return strdup(msgBuf.testo); }
额外注意事项
- 调用
receiveMessage后,必须用free()释放strdup分配的内存,避免内存泄漏。 - 多进程/线程场景下,确保消息队列权限设置正确,避免因权限不足导致接收失败。
内容的提问来源于stack exchange,提问作者Vasetto
相关产品推荐
相关产品推荐

