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

C语言SysV消息队列无法读取全部消息问题求助

问题分析与解决方案

核心错误:消息长度参数传递错误

你的代码中,msgsnd和msgrcv的第三个参数(消息长度)使用了整个结构体的大小sizeof(messages[i])/sizeof(msg),这不符合System V消息队列的API规范:

  • msgsnd要求msg_len是消息正文的长度(即结构体中msg_type之后的部分,不包含msg_type本身)。
  • msgrcv的第三个参数是接收缓冲区中用于存储正文的最大长度,同样应该匹配正文的实际大小。

错误的长度参数会导致:

  1. msgsnd向队列写入超出结构体范围的内存数据(未定义行为),破坏消息结构。
  2. msgrcv尝试读取的长度与队列中存储的消息正文长度不匹配,导致后续读取失败。

修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>

// Define a structure for our messages
struct message {
  long msg_type;
  char msg_text[100];
};

int main() {
  key_t key;
  int msg_id;
  struct message msg;

  // Generate a key for the message queue
  key = ftok("progfile", 'A');
  if (key == -1) {
    perror("ftok failed");
    exit(EXIT_FAILURE);
  }

  // Create the message queue
  msg_id = msgget(key, 0666 | IPC_CREAT);
  if (msg_id == -1) {
    perror("msgget failed");
    exit(EXIT_FAILURE);
  }

  // Prepare messages to send
  struct message messages[3] = {{1, "This is message with priority 1"},
                                {2, "This is message with priority 2"},
                                {3, "This is message with priority 3"}};

  // Calculate message text length (excluding msg_type)
  size_t msg_text_len = sizeof(msg.msg_text);

  // Send the messages
  for (int i = 0; i < 3; i++) {
    if (msgsnd(msg_id, &messages[i], msg_text_len, 0) == -1) {
      perror("msgsnd failed");
      exit(EXIT_FAILURE);
    }
  }

  // Receive the messages
  for (int i = 1; i <= 3; i++) {
    memset(&msg, 0, sizeof(msg));
    ssize_t recv_len = msgrcv(msg_id, &msg, msg_text_len, 0, IPC_NOWAIT);
    if (recv_len != -1) {
      printf("Received message: %s\n", msg.msg_text);
    } else {
      perror("msgrcv failed");
      printf("No message in the queue\n");
    }
  }

  // Destroy the message queue
  if (msgctl(msg_id, IPC_RMID, NULL) == -1) {
    perror("msgctl failed");
    exit(EXIT_FAILURE);
  }

  return 0;
}

关键修正点

  • 使用sizeof(msg.msg_text)作为消息长度,确保只传递正文部分。
  • 添加了错误检查(perror),方便排查API调用失败的原因。
  • 修复了printf中的换行符(原代码中是无效的换行,改为\n)。

同进程/跨进程差异的原因

当拆分到两个独立进程时,内存布局的巧合可能让错误的长度参数没有触发严重的未定义行为,消息能被“侥幸”正确读取;但在同一个进程中,msgsnd写入的越界数据会直接破坏消息队列中的后续消息结构,导致msgrcv无法解析剩余消息。

残留消息队列清理

如果之前运行的程序没有正常执行msgctl,可以用以下命令手动清理:

ipcrm -q <msg_id>

(msg_id可以通过ipcs -q命令查看)

内容的提问来源于stack exchange,提问作者Edward Wang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:42:01