2014-05-06 81 views
0

我想創建一些中國耳語(或電話)遊戲。使用管道連接子進程

我創建了一定數量的子進程,每個子進程必須從字符串中更改1個字母。父進程更改一個字母,然後第一個子進程接受父進程修改的字符串並更改一個字母。第二個孩子接受由第一個孩子修改的字符串(2個字母已經更改)並更改一個,依此類推。

因此,我想通過管道將父母和第一個孩子以及每兩個連續的孩子連接起來。 問題是,這不適用於超過3個孩子。第三個孩子讀不到第二個孩子讀的父母。你能告訴我我做錯了什麼嗎?

int nrch; 
    nrch=(int) strtol(argv[2], (char **)NULL, 10); 
    msg=argv[3]; 
    printf("Parent: erhalten: %s\n", msg); 
    int i=0; 
    msg=modify(argv[3],nrch); 
    printf("Parent: weiter: %s\n", msg); 
    pid_t pids[10]; 
    int fd[2]; 
    int fdold[2]; 

    if (pipe(fdold) == -1) { 
     error("Can't create the pipe"); 
    } 

    /* Start children. */ 
    for (i = 0; i < nrch; ++i) { 
     if (pipe(fd) == -1) { 
      error("Can't create the pipe"); 
     } 
     if ((pids[i] = fork()) < 0) { 
       error("Can't fork process"); 
     } 
     else if (pids[i] == 0) { 

      //dup2(fd[0], 0); 
      if(i==0){ 
       close(fdold[1]); 
       close(fd[0]); 
       read(fdold[0],msg,sizeof(msg)); 
       printf("child%d: erhalten: %s\n", (i+1), msg); 
        msg=modify(msg,i); 
       printf("child%d: weiter: %s\n", (i+1), msg); 
       write(fd[1],msg,sizeof(msg)); 
       exit(0); 
      } 
      else if(i==(nrch-1)){ 
       close(fdold[1]); 
       read(fdold[0],msg,sizeof(msg)); 
       printf("child%d: erhalten: %s\n", (i+1), msg); 
        msg=modify(msg,i); 
       printf("child%d: weiter: %s\n", (i+1), msg); 
       printf("child%d: Ende: %s\n", (i+1), msg); 

        exit(0); 
      } 
      else{ 
       close(fdold[1]); 
       close(fd[0]); 
       read(fdold[0],msg,sizeof(msg)); 

       printf("child%d: erhalten: %s\n", (i+1), msg); 
        msg=modify(msg,i); 
       printf("child%d: weiter: %s\n", (i+1), msg); 

       write(fd[1],msg,sizeof(msg)); 
       exit(0); 
      } 
     } 
     else{ 
      if(i!=0){ 
       close(fd[1]); 
      } 
      else{ 
       write(fdold[1], msg,sizeof(msg)); 

      } 
      if(i>1){ 
       close(fdold[0]); 
      } 
     } 
     pid_t wpid; 
     int status; 
     wpid = wait(&status); 
     memcpy(fdold,fd,(sizeof(int)*2)); 
    } 
    close(fd[0]); 

回答

1

我認爲你的孩子的代碼過於複雜。在循環的每次迭代中,您似乎也都是從父級寫入數據。

您正確地爲每個子進程創建一個管道,但是我沒有看到將管道的一端從一個兄弟傳遞到另一個兄弟的機制,這是父節點需要管理的東西。

在下面的代碼中,我使用父級中的prev_in將管道的讀取側從父級傳遞到第一個子級,然後從兄弟級傳遞到兄弟,最後父級將此用作其管道的讀取側。

我沒有檢查此代碼是否存在可能存在的任何緩衝區溢出問題,我只查看了文件描述符管理問題,您應該小心檢查其他錯誤。

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

char *modify (char *word, int num) 
{ 
    printf ("Modify `%s', (%d)\n", word, num); 
    word [num] = 'x'; 
    return word; 
} 

void 
whisper (int id, int in, int out) 
{ 
    char msg [100]; 

    read(in, msg, sizeof(msg)); 
    printf("child%d: heard: %s\n", id, msg); 
    modify (msg, id); 
    printf("child%d: says: %s\n", id, msg); 
    write(out, msg, sizeof(msg)); 
} 

void 
start_whisper (int in, int out, char *msg) 
{ 
    char buf [100]; 

    printf ("Parent, starting a whisper with `%s'\n", msg); 
    write(out, msg, strlen (msg) + 1); /* Also send the NUL. */ 

    read(in, buf, sizeof(buf)); 
    printf("Parent, heard back: %s\n", buf); 
} 

int 
main (int argc, char *argv []) 
{ 
    int nrch, i; 
    char *msg; 
    pid_t pids[10]; 

    nrch=(int) strtol(argv[2], (char **)NULL, 10); 
    printf ("Number of children = %d\n", nrch); 

    msg = argv[3]; 
    printf("Parent: original message: %s\n", msg); 

    if (nrch == 0 || nrch > strlen (msg)) 
    error ("Invalid number of children"); 

    msg = modify (msg, nrch); 
    printf("Parent: will start by saying: %s\n", msg); 

    int fdold[2]; 
    int prev_in, parent_in, parent_out; 

    if (pipe(fdold) == -1) { 
    error("Can't create the pipe"); 
    } 
    printf ("Parent Read: %d, Write: %d\n", fdold [0], fdold [1]); 

    parent_in = fdold [0]; 
    parent_out = fdold [1]; 

    /* Start children. */ 
    prev_in = parent_in; 
    for (i = 0; i < nrch; ++i) 
    { 
     int fd[2]; 
     if (pipe (fd) == -1) { 
     error ("Can't create the pipe"); 
     } 
     if ((pids[i] = fork()) < 0) { 
     error("Can't fork process"); 
     } 
     else if (pids[i] == 0) 
     { 
      /* Child. */ 
      int my_in, my_out; 

      close (fd [0]); /* The sibling read handle, this becomes prev_in 
          and is passed to the next sibling. */ 
      close (parent_out); /* The parent write handle, only the parent 
           wants to hold this, every child will 
           close it. */ 

      my_in = prev_in; 
      my_out = fd [1]; 

      whisper (i, my_in, my_out); 
      exit (0); 
     } 
     else 
     { 
      /* Parent. */ 
      close (prev_in); /* The PREV_IN was passed the child we just 
           created, we no longer need this. */ 
      prev_in = fd [0]; /* The read handle from the pipe we just made 
           will be passed to the next sibling. */ 
      close (fd [1]); /* The write handle from the pipe we just made 
          was grabbed by the child we just made, we no 
          longer need this. */ 
     } 
    } 

    start_whisper (prev_in, fdold [1], msg); 

    pid_t wpid; 
    int status; 
    wpid = wait(&status); 

    return 0; 
}