【问题标题】:Is this how message queues are supposed to work?这是消息队列应该如何工作的方式吗?
【发布时间】:2017-06-18 17:36:45
【问题描述】:

我正在尝试了解消息队列。在我看到的示例中,msg strunct 将只有一个属性,但第一个属性(类型)必须是long。因此,它类似于struct msg{long mtype; char text[100]};

我尝试添加一个新的int 属性x 以查看我是否同时收到了文本和数字,并且它有效。

这就是消息队列的工作方式吗?我可以在struct 中拥有尽可能多的属性吗?

另外,是否可以调用 msgrcvmsgsnd 函数并将长度参数设置为 sizeof(send) - sizeof(send.x),因为我知道结构的大小并不总是与 @ 的总和相同每个属性的987654330@? 谢谢。

int main(){

    struct msg{
        long mtype;
        char text[100];
        int x;
    };

    int key = ftok(".", 10);
    int qid = msgget(key, 0666|IPC_CREAT);

    int pid = fork();

    if(pid == 0){
        struct msg send;
        send.mtype = 1;
        strcpy(send.text, "hello");
        send.x = 99;
        if(msgsnd(qid, (void*)&send, sizeof(send) - sizeof(send.x), 0)<0){
             printf("Error child: ");
        }
    }
    else{
        struct msg recieve;
        if(msgrcv(qid, (void*)&recieve, sizeof(recieve) - sizeof(recieve.x), 1, 0)<0){
             perror("Error parent: ");
        };
        printf("text: %s\nnumber: %d", recieve.text, recieve.x);
    }

    return 0;
}

【问题讨论】:

    标签: c unix message-queue


    【解决方案1】:

    来自man page,在:

    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
    

    msgp 定义为:

    msgp 参数是一个指向调用者定义的结构的指针 如下一般形式:

          struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };
    

    粗体是我的

    这里的重点是结构是调用者定义的。因此只要输入结构(msgsnd 发送)和输出结构(msgrcv 接收)相同,mtype 后面的数据可以是任何你想要的数据(只要你正确指定了大小)。对于你的情况,你真的只需要:

    msgsnd(qid, (void*)&send, sizeof(send) - sizeof(send.mtype), 0)
    

    msgrcv(qid, (void*)&recieve, sizeof(recieve) - sizeof(send.mtype), 1, 0)
    

    【讨论】:

      【解决方案2】:

      char[] 只是一个占位符,您可以在所需的长 mtype 字段之后的结构中包含任何您想要的内容。 msgsnd() 调用的大小不包括 mtype。

      你几乎说对了。

      这是一个工作版本:

      #include <stdio.h>
      #include <string.h>
      #include <sys/types.h>
      #include <sys/ipc.h>
      #include <sys/msg.h>
      
      int main(void){
      
          struct msg {
              long mtype;
              char text[100];
              int x;
          };
      
          size_t sz = sizeof(struct msg) - sizeof(long);  <=== /* SIZE */
          int key = ftok(".", 10);
          int qid = msgget(key, 0666|IPC_CREAT);
      
          int pid = fork();
      
          if (pid == 0){
              struct msg send;
              send.mtype = 1;
              strcpy(send.text, "hello");
              send.x = 99;
              if (msgsnd(qid, (void*)&send, sz, 0)<0){
                   perror("Error child: ");
              }
          } else {
              struct msg recieve;
              if(msgrcv(qid, (void*)&recieve, sz, 1, 0)<0){
                   perror("Error parent: ");
              };
              printf("text: %s\nnumber: %d\n", recieve.text, recieve.x);
          }
      
          return 0;
      }
      

      【讨论】:

      • 感谢您的回答,但我看不出您的版本和我的版本有什么区别。你的 size_t sz = sizeof(struct msg) - sizeof(long) 相当于我的 sizeof(recieve) - sizeof(recieve.x)。我错过了什么吗?
      • 只有在 intlong 的大小相同时,它才在数字上“等效”。
      • 语义上,减去mtype的大小是正确的。减去您要发送的某些字段是不正确的(例如x)。
      【解决方案3】:
      int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
      

      由于msgp 参数被声明为const void*,您可以使用任何您想要的数据类型。没有什么说它必须是 struct,只有 longchar[]。这意味着你可以做sizeof(send)。您无需针对要发送的额外结构成员进行调整。实际上,这样做会导致问题,因为不会处理整个结构。唯一重要的是msgrcv() 使用与之前的msgsnd() 相同的结构。见this example

      【讨论】:

      • char[] 只是一个占位符,您可以在所需的long mtype 字段之后在结构中包含任何您想要的内容。 msgsnd() 调用的大小不包括 mtype
      • @JohnHascall mtype 是必需的吗?
      • 是的,消息类型的结构必须以long 开头。您不必将其称为 mtype,但这是正常做法。
      猜你喜欢
      • 1970-01-01
      • 2014-02-13
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 2010-09-28
      • 2015-10-20
      • 1970-01-01
      • 2012-08-03
      相关资源
      最近更新 更多