2016-12-24 77 views
0

我在使用我的代码时遇到了一些麻烦。它应该创建一个消息队列并发送消息,而不是等待另一个程序接收该消息并回答。问题是,当我运行它时,我在msgsnd和msgrcv上都得到了一个无效的参数。消息队列给了我一个无效的参数

#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/msg.h> 

typedef struct my_msg{ 
    long type; 
    char text[100]; 
    char sqdr; 
}message; 

static void score(int messagge_id, char* A_B){ 
    message send; 
    send.type=1; 
    strcpy(send.text, "Try to score"); 
    send.sqdr = *A_B; 
    if((msgsnd(messagge_id, &send, sizeof(send), 0))<0)perror("Error msgsnd\n"); 
    sleep(3); 
    if((msgrcv(messagge_id, &send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n"); 
    int test=atoi(send.text); 
    printf("%d\n", test); 
} 


int main(){ 
    int caso, key; 
    char team= 'A'; 
    key=1234; 
    int msg_id=msgget(key, S_IRUSR|S_IWUSR); 
    printf("Try function score\n"); 
    score(msg_id, &team); 
    printf("After score\n"); 
return 0; 
} 
+2

为什么你不错误检查'msgget()'调用?它成功了吗?是否有另一个进程创建了消息队列? –

+0

我会尝试检查msgget,但我认为问题不在于创建消息队列,因为我没有编写第二个程序。它可能是使用的关键问题吗? – Leo

+1

我认为这很可能是因为您没有使用密钥'IPC_PRIVATE'或指定'IPC_CREAT'作为标记(以及'S_IRUSR | S_IWUSR'),因此您没有附加到预先存在的消息队列,并没有创建它。参见['msgget()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/msgget.html)(和 ['msgctl()'](http://pubs.opengroup.org/ onlinepubs/9699919799/functions/msgctl.html)在完成后删除消息队列)。请注意,一旦队列被创建,它将一直存在直到被删除。 –

回答

0

您需要确保该消息队列创建。您可以使用密钥​​3210或将IPC_CREAT添加到标志。您还需要尝试正确阅读该消息。您发送了“类型1”消息并尝试读取“类型4”消息,因此读取挂起。

此代码还会删除消息队列。如果它是一个私有队列(这种队列在程序终止时被删除),这并不重要,但对于使用IPC_CREAT和用户定义的密钥的队列来说,这一点非常重要。 (我还更改了消息文本,以便atoi()返回的内容比零更有趣并且令人信服 - 代码还使用单独的发送缓冲区和接收缓冲区,以便我们知道代码不会作弊并重新使用缓冲区中的数据。)

#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/msg.h> 
#include <fcntl.h> 

typedef struct my_msg 
{ 
    long type; 
    char text[100]; 
    char sqdr; 
} message; 

static void score(int messagge_id) 
{ 
    message send; 
    message recv; 
    send.type = 1; 
    strcpy(send.text, "47 tries to score"); 
    send.sqdr = 'A'; 
    if ((msgsnd(messagge_id, &send, sizeof(send), 0)) < 0) 
     perror("Error msgsnd"); 
    printf("Dozing...\n"); 
    sleep(3); 
    printf("Unslumbering...\n"); 
    if ((msgrcv(messagge_id, &recv, sizeof(recv), -4, 0)) == -1) 
     perror("Error msgrcv"); 
    int test = atoi(recv.text); 
    printf("%d\n", test); 
} 

int main(void) 
{ 
    int key = 1234; 
    int flags = S_IRUSR|S_IWUSR|IPC_CREAT; 
    // int key = IPC_PRIVATE; 
    // int flags = S_IRUSR|S_IWUSR; 
    int msg_id = msgget(key, flags); 
    if (msg_id < 0) 
     perror("Error msgget"); 
    else 
    { 
     printf("Try function score\n"); 
     score(msg_id); 
     printf("After score\n"); 
     if (msgctl(msg_id, IPC_RMID, 0) < 0) 
      perror("Error msgctl"); 
    } 
    return 0; 
} 

示例输出:

Try function score 
Dozing... 
Unslumbering... 
47 
After score 

有 '休眠' 和 '警',当然之间有3秒的暂停。

+0

非常感谢! – Leo

-1

使用这样的: -

if((msgsnd(messagge_id, (void *)&send, sizeof(send), 0))<0)perror("Error msgsnd\n"); 

if((msgrcv(messagge_id, (void *)&send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n"); 
+0

什么是重大变化?对'void *'的转换不重要;它没有改变。 –

+0

请分享完整的错误报告...谢谢 – Codesingh

+0

输出为“尝试函数分数。错误消息:无效参数。错误msgrcv:无效参数。得分后”。 – Leo