【问题标题】:IPC using message queue in C: Error in receivingIPC在C中使用消息队列:接收错误
【发布时间】:2014-05-04 15:34:48
【问题描述】:

我正在 C linux 中实现消息队列。我正在发送integer = 17 并接收integer = 0。请看下面,让我知道我的 msgsndmsgrcv 函数有什么问题。 请注意:rbuf 会将数据存储在rbuf->m->msglenrbuf->mtype 中。

发送中

msgsnd(msqid, sbuf,sizeof(int), 0);
printf("\nmsglen = %d",rbuf->m->msglen);  // 17

在接收过程中。两者都有相同的 msqid。我已经验证过了。

msgrcv(msqid, rbuf, sizeof(int), 1, 0);
printf("\nmsglen = %d",rbuf->m->msglen); // 0

//msqid=98305, some valid id

这是我在另一个文件中定义的结构定义。

typedef struct message1
{
    int msglen;
    unsigned char *cp;
}msg1;

typedef struct msgbuf
{
    long    mtype;
    msg1    *m;
} message_buf;

【问题讨论】:

  • msgrcv() 调用后的errno 值是多少?
  • 没有。收到的字节数
  • 对不起,我用正确的问题更新了我的评论。 errno 值是多少?
  • 请显示完整代码
  • 在发送过程中你正在打印rbuf->m->msglen - 那不应该是sbuf,你刚刚发送的消息吗?

标签: c linux ipc message-queue


【解决方案1】:
//header files
#include"msgbuf.h"  //where I have put my structures
#define AUTOMATIC 1
#define USER_DATA 2

int main()
{
    int msgflg = IPC_CREAT | 0666,ch,len=0;
    size_t msgsize = 0;
    int msqid;
    key_t key;
    message_buf *sbuf;
    char ans;
    char *data;
    key = ftok("/home/user",15);

    printf("Do you want to send messages\t");
    scanf("%c",&ans);
    getchar();
    if (((ans=='y' || ans=='Y') && (msqid = msgget(key, msgflg )) ==-1))
    {       perror("msgget");
            exit(1);
    }
    else
    fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid);

    while(ans=='y' || ans=='Y')
    {
            printf("\n1. Automatic data\n2. Enter data\n3. Exit\nEnter your choice\t");
            scanf("%d",&ch);
            getchar();
            switch(ch)
            {
                    case AUTOMATIC: len=strlen("Did you get this?");

                                    sbuf=malloc(len+sizeof(int));
                                    memset(sbuf, 0, sizeof(message_buf));
                                    sbuf->m=malloc(len+sizeof(int));
                                    memset(sbuf->m, 0, sizeof(msg1));

                                    sbuf->m->msglen=len;
                                    sbuf->m->cp=malloc(sizeof(len));
                                    strncpy(sbuf->m->cp, "Did you get this?",strlen("Did you get this?"));
                                    sbuf->m->cp[strlen(sbuf->m->cp)]='\0';
                                    break;
                    case USER_DATA: printf("\nEnter data\t");
                                    fflush(stdout);
                                    len = getline(&data, &msgsize, stdin);

                                    sbuf=malloc(len+sizeof(int));
                                    memset(sbuf, 0, sizeof(message_buf));
                                    sbuf->m=malloc(len+sizeof(int));
                                    memset(sbuf->m, 0, sizeof(msg1));

                                    strcpy(sbuf->m->cp, data);
                                    sbuf->m->cp[strlen(sbuf->m->cp)]='\0';
                                    sbuf->m->msglen=len;
                                    break;
                    case 3: msgctl(msqid, IPC_RMID, NULL);
                            printf("\nQueue with q id = %d is removed\n",msqid);
                            exit(1);
                    default:printf("\nTRY AGAIN\t");
                            scanf("%c",&ans);
                            getchar();
            }
            printf("\nmsglen = %d\nmsgcp= %s",sbuf->m->msglen,sbuf->m->cp);
             /* Send a message */
            sbuf->mtype=1;
            if (msgsnd(msqid, sbuf,2*sizeof(int), 0) < 0)
            {
        printf("Msg q id= %d\nMsg type= %d\nMsg Text %s\nMsg Len= %d\n", msqid, sbuf->mtype, sbuf->m->cp,sbuf->m->msglen);
                    perror("msgsnd");
                    exit(1);
            }
            else
            printf("\nMessage: %s\n Sent\n", sbuf->m->cp);
    }
    msgctl(msqid, IPC_RMID, NULL);
    printf("\nQueue with q id = %d is removed\n",msqid);
    return 0;
}

正在接收代码

//header files
#include"msgbuf.h"
int main()
{
    int msqid;
    key_t key;
    int msgflg = 0666;
    message_buf  *rbuf;
    int msg_len_rcvd=0;

    rbuf=malloc(150);
    rbuf->m=malloc(100);
    key = ftok("/home/user",15);
    if ((msqid = msgget(key, msgflg)) ==-1)
    {
            perror("msgget");
            exit(1);
    }
    printf("\n\n%d\n",msqid);
    /* Receive an answer of message type 1.   */
    while(1)
    {
            if ( (msg_len_rcvd=msgrcv(msqid, rbuf, 2*sizeof(int), 1, 0)) < 0)
            {
                    perror("msgrcv");
                    exit(1);
            }
            else
            {
                    printf("\n Number of bytes received:: %d", msg_len_rcvd);
                    printf("\nmtype1 = %d",rbuf->mtype);
                    printf("\nmsglen= %d",rbuf->m->msglen);
            }
            break;
    }
    return 0;
}

【讨论】:

    【解决方案2】:

    您正在发送一条消息,其中包含指向您的 message1 结构的指针。接收进程取消引用该指针,但在该进程中它不指向同一事物。事实上,我很惊讶你没有遇到段错误。

    你应该像这样定义 msgbuf:

    typedef struct msgbuf
    {
        long    mtype;
        msg1    m;
    } message_buf;
    

    因此 msg1 结构包含在 msgbuf 中,而不是被它指向。

    另外,您需要指定的大小是 sizeof(message_buf),而不是 sizeof(int)。

    【讨论】:

    • 两个进程在同一台机器上。我是学生所以只是尝试一下。而我之所以做sizeof(int)是因为我想先接收我的消息的长度,这样我就可以在接收过程中为cp分配空间,然后再接收cp。
    • @user3436838 他们是否在同一台机器上并不重要。不同的进程不能互相访问内存。
    • 谢谢先生。它正在工作。但是问题是:我先是想发送msglen,发送成功了再想发送cp。我为 cp 分配了空间 rbuf->m.cp=malloc(rbuf->m.msglen); 然后 msgrcv(msqid,rbuf,rbuf->m.msglen,1 ,0) 它给出了段错误。关于它的任何想法。
    • @user3436838 同样的问题。不能发送任何指针,比如malloc返回的。
    • 您可以,但您必须在 msgbuf 结构中发送整个内容。为 msgbuf 及其嵌入的数组内容分配足够的空间。
    猜你喜欢
    • 1970-01-01
    • 2013-12-06
    • 2020-11-21
    • 2014-05-03
    • 2014-04-05
    • 2013-01-05
    • 2012-09-19
    • 2021-03-12
    • 2013-04-16
    相关资源
    最近更新 更多