Linux编程。如何发送带有消息队列的数组?

时间:2018-12-18 16:06:39

标签: c linux ipc message-queue

我有writer.c和reader.c,我试图从writer发送数组,然后在阅读器中打印数字。

        //writer.c

    #include <stdio.h> 
    #include <sys/ipc.h> 
    #include <sys/msg.h> 

    // structure for message queue 
    struct mesg_buffer { 
        int mesg_type; 
        int a[5];

    } message; 

    int main() 
    { 
    message.a [0] = 5;
    message.a [1] = 10;
    message.a [2] = 15;
    message.a [3] = 34;
    message.a [4] = 34;

        key_t key; 
        int msgid; 

        // ftok to generate unique key 
        key = ftok(".", 65); 

        // msgget creates a message queue 
        // and returns identifier 
        msgid = msgget(key, 0666 | IPC_CREAT); 
        message.mesg_type = 1; 

 // msgsnd to send message 
    for(int i=0;i<5;i++)
    msgsnd(msgid, (int *) &message.a[i], sizeof(message.a[i]), 0);



        // display the message 
    for(int i=0;i<5;i++)
        printf("Data send is : %d \n", message.a[i]); 

        return 0; 
    } 

reader.c

 // C Program for Message Queue (Reader Process) 
#include <stdio.h> 
#include <sys/ipc.h> 
#include <sys/msg.h> 

// structure for message queue 
struct mesg_buffer { 
    int mesg_type; 
    int a[5];
} message; 

int main() 
{ 
    key_t key; 
    int msgid; 

    // ftok to generate unique key 
    key = ftok(".", 65); 

    // msgget creates a message queue 
    // and returns identifier 
    msgid = msgget(key, 0666 | IPC_CREAT); 

    // msgrcv to receive message
    for(int i=0; i<5; i++)
   msgrcv(msgid, &message, sizeof(message.a[i]), 1, 0); 

    for(int i=0; i<5; i++)
    printf("Data Received is : %d \n",  
                    message.a[i]); 

    // to destroy the message queue 
    msgctl(msgid, IPC_RMID, NULL); 

    return 0; 
} 

我首先运行writer.c,这是我的输出:

  

数据发送为:5

     

数据发送为:10

     

数据发送为:15

     

数据发送为:34

     

数据发送为:34

但是当我运行reader.c时,程序卡住了,什么也没发生。有什么建议如何传递数组吗?

编辑:似乎仅在msgsnd和msgrcv中传递了消息,即可解决问题。

for(int i=0;i<5;i++)
    msgsnd(msgid, &message, sizeof(message), 0); 

3 个答案:

答案 0 :(得分:1)

您的代码调用未定义的行为。

由于要按整数发送整数,因此应使用sizeof(message.a[i])(即一个元素的大小),而不要使用sizeof(message.a)(即整个数组a的大小)

msgsnd(msgid, (int *) &message.a[i], sizeof(message.a), 0);
                                            ^^^^^^^^^

简而言之,这意味着您正在数组后面传递一些垃圾。

答案 1 :(得分:1)

编辑:仔细阅读 man msgsnd 后,看起来类型应该是发送的每条消息的第一个字段,但是您要分别将结构的每个字段传递给每个消息msgsnd调用,因此不会包含该类型。您需要一次发送整个结构,或者如果要发送单个单词,则需要某种中间结构类型。

这里也可能有其他一些问题。读者似乎根本没有收到任何消息。我将从检查与队列打开/发送/接收有关的所有系统调用的返回值开始,并在出现意外结果的情况下调用perror()。

第三点,如前一条评论所述,由于您确实想要sizeof(message.a [i]),因此对msgsnd的调用可能无法正确进行。绝对是一个问题,但不应阻止发送第一条消息

第四(这不应该引起当前问题),一旦您的读者收到,它将覆盖每次对msgrcv的调用message.a的内容。您需要先找到一种方法来保存接收到的数据,然后再将其读入消息中。

答案 2 :(得分:1)

man msgsnd

  

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

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

所以

msgsnd(msgid, (int *) &message.a[i], sizeof(message.a[i]), 0);

是错误的,您必须为要发送的每个值提供完整的消息