2016-03-10 23 views
-2

這使我煩惱幾天。 問題是我不太瞭解c中的指針和地址,所以我希望有人能夠幫助我。c中使用消息和msgsnd提取單個字符

我需要傳遞一些字符串作爲輸入參數,並創建儘可能多的生產者進程+一個消費者進程。

生產者應該分開字符串並將每個字母作爲消息發送給隊列。最後它應該發送NULL(「」)。

消費者應等待消息並將其打印出來。

整個代碼和輸出如下。通過查看輸出,我會說這個問題在生產者的某個地方。更確切地說,它在te for循環的第一行,但我不能正確的。

manager.c - 這是工作流程

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <sys/msg.h> 

int main(int argc, char *argv[], char *envp[]) { 

    printf("Starting %d processes \n", argc); 

    putenv("MSG_KEY=12345"); 

    for (int i = 1; i < argc; i++) { 
     printf("argv[%d] = %s \n", i, argv[i]); 
     pid_t producer = fork(); 

     if (producer == 0) { 
      printf("producer pid - %d\n", getpid()); 
      execl("./producer", "producer", argv[i], NULL); 
     } 
    } 

    pid_t consumer = fork(); 

    if (consumer == 0) { 
     printf("consumer pid - %d\n", getpid()); 
     execl("./consumer", "consumer", NULL); 
     exit(0); 
    } else { 
     printf("manager pid - %d\n", getpid()); 
     wait(NULL); 
    } 

    int status; 
    while(waitpid(consumer, &status, 0) == -1); 
    printf("DONE consumer\n"); 

    printf("DONE manager\n"); 

    return 0; 
} 

producer.c主程序

/* 
** writes to message queue 
*/ 

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

struct my_msgbuf { 
    long mtype; 
    char mtext[1]; 
}; 

int main(int argc, char *argv[], char *envp[]) { 
    struct my_msgbuf buf; 
    int msqid; 
    key_t key = atoi(getenv("MSG_KEY")); 

    if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) { 
     perror("msgget"); 
     exit(1); 
    } 

    buf.mtype = getpid(); 

    // I believe the error is in this for loop or to be more precise in the first line of the for loop. 
    // takes the first argument and sends characters in separate messages 
    for (int i = 0; i < strlen(argv[1]); ++i) { 
     char c = argv[1][i]; 

     strcpy(buf.mtext, &c); 

     printf ("Sending -%s-\n", buf.mtext); 
     if (msgsnd(msqid, (struct msgbuf *)&buf, strlen(buf.mtext)+1, 0) == -1) 
      perror("msgsnd"); 
    } 

    // send NULL at the end 
    memcpy(buf.mtext, "", strlen("")+1); 
    if (msgsnd(msqid, (struct msgbuf *)&buf, strlen("")+1, 0) == -1) 
     perror("msgsnd"); 

    return 0; 
} 

consumer.c

/* 
** reads from message queue 
*/ 

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

struct my_msgbuf { 
    long mtype; 
    char mtext[1]; 
}; 

int main(int argc, char *argv[], char *envp[]) { 
    struct my_msgbuf buf; 
    int msqid; 
    key_t key = atoi(getenv("MSG_KEY")); 

    if ((msqid = msgget(key, 0600 | IPC_CREAT)) == -1) { 
     perror("msgget"); 
     exit(1); 
    } 

    int flag = 0; 
    int wait_counter = 0; 
    while (wait_counter < 10) { 
     msgrcv(msqid, (struct msgbuf *)&buf, sizeof(buf)-sizeof(long), 0, flag); 

     if (errno == ENOMSG){ 
      wait_counter++; 
      printf ("Sleaping for one second...zzzZZZzzz...%d\n", wait_counter); 
      usleep(1000 * 1000); 
     } else { 
      printf("Received:\n\ttype: -%ld- \n\tchar: -%s- \n", buf.mtype, buf.mtext); 
      int compare = strcmp(buf.mtext, ""); 
      if(compare == 0){ 
       printf("NULL received\n"); 
       flag = IPC_NOWAIT; 
      } else { 
       flag = 0; 
      }  
      wait_counter = 0; 
     } 
     errno = 0; 
    } 

    if (msgctl(msqid, IPC_RMID, NULL) == -1) { 
     perror("msgctl"); 
     exit(1); 
    } else { 
     printf("Message queue removed\n"); 
    } 

    return 0; 
} 

輸出 - 我得給你這裏的屏幕截圖是因爲c/p刪除了問題,一切看起來都不錯

enter image description here

任何幫助將不勝感激!謝謝!如在下面 * buf.mtext = c中的@sergeya答案建議使用時


錯誤;

enter image description here

回答

0

正如我所說的,問題出在for循環中的生產者。我會在這裏做出改變。希望它可以幫助任何有類似問題的人。

@SergeyA給了我很好的線索,問題在於我從「strcpy」切換到「memcpy」,並且我複製了第一個字符而不是nul-終止符。 此外,我已將「strlen」更改爲「sizeof」並刪除了+1。

Producer.c

... 
for (int i = 0; i < strlen(argv[1]); ++i) { 
    char c = argv[1][i]; 

    memcpy(buf.mtext, &c, sizeof(&c)+1); 

    printf ("Sending -%c-\n", buf.mtext); 
    if (msgsnd(msqid, (struct msgbuf *)&buf, sizeof(buf.mtext), 0) == -1) 
     perror("msgsnd"); 
} 
... 
0

您的問題(他們中的一個,至少)是在這裏:

char c = argv[1][i]; 
    strcpy(buf.mtext, &c); 

strcpy()會嘗試複製儘可能多的字符存在,直到遇到NUL終止符'\0',從開始c。你需要完全複製一個字符,所以你只需要

*buf.mtext = c; 
+0

我喜歡你的意見,你可能是正確的,但你提議的修改是不是100%正確。 'producer.c:函數'main':' '製作者。c:38:13:錯誤:賦值給數組類型表達式 buf.mtext = c;' – Vedran

+0

@Vedran,true。我忘了你宣佈它是一個數組。更新了代碼。 – SergeyA

+0

這創建了一個發送消息的loooooot的循環。我不能在這裏放置一張圖片,所以我會在上面的問題結尾處加以說明。 – Vedran

相關問題