简体   繁体   English

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

[英]Linux programming. How to send array with message queue?

I have writer.c and reader.c and I am trying to send array from writer and then print the numbers in the reader. 我有writer.c和reader.c,我正在尝试从编写器发送数组,然后在阅读器中打印数字。

        //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 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; 
} 

I run firstly the writer.c and that's my output: 我首先运行writer.c,这是我的输出:

Data send is : 5 数据发送是:5

Data send is : 10 数据发送是:10

Data send is : 15 数据发送是:15

Data send is :34 数据发送是:34

Data send is : 34 数据发送是:34

But when I run the reader.c the program just stucks and nothing happens. 但是当我运行reader.c时程序就停止了,没有任何反应。 Any suggestion how to pass the array? 任何建议如何传递数组?

edit: It seems that passing only the message in msgsnd and msgrcv fixed the problem. 编辑:似乎只传递msgsnd和msgrcv中的消息修复了问题。

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

Your code invokes undefined behavior. 您的代码调用未定义的行为。

Since you want to send integer-by-integer, you should use sizeof(message.a[i]) , what is size of one element, instead of sizeof(message.a) , which is size of the whole array a . 既然你想要逐个整数发送,你应该使用sizeof(message.a[i]) ,一个元素的大小,而不是sizeof(message.a) ,它是整个数组a大小。

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

In short it means you are passing some garbage behind the array. 简而言之,这意味着你在数组后面传递一些垃圾。

Edit: After reading man msgsnd a bit close, it looks like the type is expected to be the first field of each message sent, but you're passing each field of the structure individually to each msgsnd call, so the type won't be included. 编辑:在读取man msgsnd有点接近之后,看起来类型应该是每个消息发送的第一个字段,但是你要将结构的每个字段分别传递给每个msgsnd调用,所以类型不会是包括在内。 You either need to send the entire structure at once or have some intermediate struct type if you want to send individual words. 您需要立即发送整个结构,或者如果要发送单个单词,则需要一些中间结构类型。

There could be a few other issues here too. 这里可能还有一些其他问题。 It seems like the reader is not receiving any messages at all. 似乎读者根本没有收到任何消息。 I would start by checking the return values of all the system calls related to queue opening/sending/receiving and calling perror() in case of an unexpected result. 我将首先检查与队列打开/发送/接收相关的所有系统调用的返回值,并在出现意外结果时调用perror()。

Third, as the previous comment mentions, the calls to msgsnd are likely not going to go through correctly because you really want sizeof(message.a[i]). 第三,正如之前的评论所提到的,对msgsnd的调用很可能无法正确进行,因为你真的想要sizeof(message.a [i])。 This is defintely an issue, but it shouldn't stop the first message from being sent 这绝对是一个问题,但它不应该阻止发送第一条消息

Fourth (and this one shouldn't be causing the current issue), once you get your reader receiving, it's going to overwrite the contents of message.a on each call to msgrcv. 第四个(这个不应该导致当前的问题),一旦你的读者接收到,它将在每次调用msgrcv时覆盖message.a的内容。 You need to find a way to preserve the received data before reading it into message again. 您需要找到一种方法来保留接收的数据,然后再将其读入消息。

man msgsnd says 男人msgsnd

The msgp argument is a pointer to caller-defined structure of the following general form: msgp参数是指向以下一般形式的调用者定义结构的指针:

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

So 所以

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

is wrong, you had to have a complete message for each value you want so send 是错误的,你必须为你想要发送的每个值都有一个完整的消息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM