2016-12-24 74 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