You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 tipo
  • receiveMessage第二个参数改为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 09:05:39