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

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

C library message queue didn't read all messages

问题

我运行这段代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/ipc.h>
  5. #include <sys/msg.h>
  6. #include <sys/types.h>
  7. // 为消息定义一个结构体
  8. struct message {
  9. long msg_type;
  10. char msg_text[100];
  11. };
  12. int main() {
  13. key_t key;
  14. int msg_id;
  15. struct message msg;
  16. // 为消息队列生成一个键
  17. key = ftok("progfile", 'A');
  18. // 创建消息队列
  19. msg_id = msgget(key, 0666 | IPC_CREAT);
  20. // 准备要发送的消息
  21. struct message messages[3] = {{1, "This is message with priority 1"},
  22. {2, "This is message with priority 2"},
  23. {3, "This is message with priority 3"}};
  24. // 发送消息
  25. for (int i = 0; i < 3; i++) {
  26. msgsnd(msg_id, &messages[i], sizeof(messages[i]), 0);
  27. }
  28. // 接收消息
  29. for (int i = 1; i <= 3; i++) {
  30. memset(&msg, 0, sizeof msg);
  31. if (msgrcv(msg_id, &msg, sizeof(msg), 0, IPC_NOWAIT) != -1) {
  32. printf("Received message: %s\n", msg.msg_text);
  33. } else {
  34. printf("No message in the queue\n");
  35. }
  36. }
  37. // 销毁消息队列
  38. msgctl(msg_id, IPC_RMID, NULL);
  39. return 0;
  40. }

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

  1. Received message: This is message with priority 1
  2. No message in the queue
  3. 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:

  1. #include &lt;stdio.h&gt;
  2. #include &lt;stdlib.h&gt;
  3. #include &lt;string.h&gt;
  4. #include &lt;sys/ipc.h&gt;
  5. #include &lt;sys/msg.h&gt;
  6. #include &lt;sys/types.h&gt;
  7. // Define a structure for our messages
  8. struct message {
  9. long msg_type;
  10. char msg_text[100];
  11. };
  12. int main() {
  13. key_t key;
  14. int msg_id;
  15. struct message msg;
  16. // Generate a key for the message queue
  17. key = ftok(&quot;progfile&quot;, &#39;A&#39;);
  18. // Create the message queue
  19. msg_id = msgget(key, 0666 | IPC_CREAT);
  20. // Prepare messages to send
  21. struct message messages[3] = {{1, &quot;This is message with priority 1&quot;},
  22. {2, &quot;This is message with priority 2&quot;},
  23. {3, &quot;This is message with priority 3&quot;}};
  24. // Send the messages
  25. for (int i = 0; i &lt; 3; i++) {
  26. msgsnd(msg_id, &amp;messages[i], sizeof(messages[i]), 0);
  27. }
  28. // Receive the messages
  29. for (int i = 1; i &lt;= 3; i++) {
  30. memset(&amp;msg, 0, sizeof msg);
  31. if (msgrcv(msg_id, &amp;msg, sizeof(msg), 0, IPC_NOWAIT) != -1) {
  32. printf(&quot;Received message: %s\n&quot;, msg.msg_text);
  33. } else {
  34. printf(&quot;No message in the queue\n&quot;);
  35. }
  36. }
  37. // Destroy the message queue
  38. msgctl(msg_id, IPC_RMID, NULL);
  39. return 0;
  40. }

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

  1. Received message: This is a message with priority 1
  2. No message in the queue
  3. 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,它们应该是

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

  1. 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

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

and

  1. 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:

确定