C库消息队列未读取所有消息。

huangapple go评论62阅读模式
英文:

C library message queue didn't read all messages

问题

我运行这段代码:

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

// 为消息定义一个结构体
struct message {
  long msg_type;
  char msg_text[100];
};

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

  // 为消息队列生成一个键
  key = ftok("progfile", 'A');

  // 创建消息队列
  msg_id = msgget(key, 0666 | IPC_CREAT);

  // 准备要发送的消息
  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"}};

  // 发送消息
  for (int i = 0; i < 3; i++) {
    msgsnd(msg_id, &messages[i], sizeof(messages[i]), 0);
  }

  // 接收消息
  for (int i = 1; i <= 3; i++) {
    memset(&msg, 0, sizeof msg);
    if (msgrcv(msg_id, &msg, sizeof(msg), 0, IPC_NOWAIT) != -1) {
      printf("Received message: %s\n", msg.msg_text);
    } else {
      printf("No message in the queue\n");
    }
  }

  // 销毁消息队列
  msgctl(msg_id, IPC_RMID, NULL);

  return 0;
}

我预期的输出应该是打印出所有三条消息,但实际上只打印出:

Received message: This is message with priority 1
No message in the queue
No message in the queue

而且 msgctl 没有运行,因为当我运行 ipcs 时,即使这段代码已经运行完毕,我仍然可以看到消息队列仍然存在。

根据我的阅读,msgrcv(msg_id, &amp;msg, sizeof(msg), 0, IPC_NOWAIT) 应该读取并删除队列中的第一条可用消息,类型参数设置为 0。但实际上,它只读取了一条消息,然后无法读取任何消息,这让我感到困惑。我使用 gdb 进行了调试,并发现即使消息队列仍然有消息,msgrcv 也无法检索消息。另一件奇怪的事情是,如果我将此代码拆分为两个文件,并在两个进程中运行发送和接收逻辑,接收进程可以读取所有 3 条消息。我不知道其中的差异是什么。谢谢您的任何帮助!

英文:

I'm running this code:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/ipc.h&gt;
#include &lt;sys/msg.h&gt;
#include &lt;sys/types.h&gt;

// 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(&quot;progfile&quot;, &#39;A&#39;);

  // Create the message queue
  msg_id = msgget(key, 0666 | IPC_CREAT);

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

  // Send the messages
  for (int i = 0; i &lt; 3; i++) {
    msgsnd(msg_id, &amp;messages[i], sizeof(messages[i]), 0);
  }

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

  // Destroy the message queue
  msgctl(msg_id, IPC_RMID, NULL);

  return 0;
}

What I expect is it prints out all three messages, but actually it only prints:

Received message: This is a message with priority 1
No message in the queue
No message in the queue

And msgctl did not run because when I ipcs, I can still see the message queue alive even after this code finished.

From what I read, msgrcv(msg_id, &amp;msg, sizeof(msg), 0, IPC_NOWAIT) will read and remove the 1st message available, with the type arg set to 0. But actually, it reads only 1 message and then it cannot read any message, which confused me. I debugged using gdb, and found that even when the message queue still has messages, msgrcv won't retrieve the message. The other strange thing is, if I split this code into two files and run the send and read logic in two processes, the read process can read all 3 messages. I don't know what is the difference here. Thank you for any help!

答案1

得分: 2

错误出在msgsndmsgrcv,它们应该是

msgsnd(msg_id, &messages[i], sizeof(messages[i].msg_text), 0);

if (msgrcv(msg_id, &msg, sizeof(msg.msg_text), 0, IPC_NOWAIT) != -1)

第三个参数msgsz应该只包含消息的msg_text的大小。

英文:

The error is in msgsnd and msgrcv, they should be

msgsnd(msg_id, &amp;messages[i], sizeof(messages[i].msg_text), 0);

and

if (msgrcv(msg_id, &amp;msg, sizeof(msg.msg_text), 0, IPC_NOWAIT) != -1) 

The 3rd arg msgsz should only contain the size of the msg_text of the message.

huangapple
  • 本文由 发表于 2023年6月26日 05:04:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552396.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定