2017-03-12 17 views
1

パイプと子プロセスを扱う際にいくつか問題が発生しました。親と各子 パイプとフォークが間違った出力になります

  • 間私は

    1. に必要

      (フォークを使用して、4人の子を作成する)

    2. (パイプを用いて双方向通信を確立するには)数を含むファイルcard.txtからデータを読み出しますストリング
    3. の子1はAE、子2のGET BFなど
    4. 上の一個のメンバー変数を選択し得る、各子 ABCDEFGHにラウンドロビン方式で文字列を配布 - > SEを

      $ ./a.out 1C < card.txt 
          Child : 1, pid 1593 : 
          <S2 S3 S9 ><H9 H6 HA H8 ><C6 CK ><D8 DQ D7 D3 > 
          Child : 2, pid 1594 : 
          <SA S6 S7 S4 ><H4 HJ H7 ><CQ C9 CT ><DT D2 D9 > 
          Child : 3, pid 1595 : 
          <SQ S5 ><H2 ><C7 C5 C8 CA C4 CJ C3 ><DA D5 > 
          Child : 4, pid 1596 : 
          <S8 SJ SK ST ><HK HT H5 H3 HQ ><C2 ><D4 D6 > 
          child 1: H9 
          parent: child 1 played H9 
          child 2: CQ 
          parent: child 2 played CQ 
          child 3: H2 
          parent: child 3 played H2 
          child 4: HK 
          parent: child 4 played HK 
      

      :ND

    5. 印刷を終了未使用の管を閉じるライトを使用して、親の変数()及び(読み取り)、ならびに近い()は期待出力される親プロセスに

    を変数を受けただし、実際の出力は次のとおりです。

    parent: child 1 played (null)parent: child 2 played (null)parent: child 3 played (null)parent: child 4 played (null) 
    

    なぜですか?どのように問題を解決するには?

    コードは、この出力を作成しました:あなたはchild2_parentparent_child2のような名前を使用して起動すると

    #include <stdio.h> 
    #include <string.h> 
    
    #define BUFFERSIZE 51 
    int i=0; 
        int currpid, s; 
        char *buf[BUFFERSIZE]; 
        char *array[BUFFERSIZE]; 
        int n; 
        char *buffer[100]; 
    /** child to parent pipe */ 
        int child_parent[2]; 
        /** parent to child pipe */ 
        int parent_child[2]; 
    
        /** child2 to parent pipe */ 
        int child2_parent[2]; 
        /** parent to child2 pipe */ 
        int parent_child2[2]; 
    
        /** child3 to parent pipe */ 
        int child3_parent[2]; 
        /** parent to child3 pipe */ 
        int parent_child3[2]; 
    
        /** child4 to parent pipe */ 
        int child4_parent[2]; 
        /** parent to child4 pipe */ 
        int parent_child4[2]; 
    
    void childFunction(){ 
        int j; 
         for(i = s+1; i < BUFFERSIZE; i += 4) 
         { 
          buf[j] = array[i]; 
          j++; 
         } 
         printf("\n<"); 
         int r; 
         char *e; 
         for(r = 0; r < j; r++) 
         { 
          int index; 
          e = strchr(buf[r],'S'); 
          if (e!=NULL){ 
           index = (int)(e-buf[r]); 
           if (index == 0){ 
    
            printf("%s ", buf[r]) ; 
           } 
          } 
         } 
         printf(">"); 
         printf("<"); 
         for(r = 0; r < j; r++) 
         { 
          int index; 
          e = strchr(buf[r],'H'); 
          if (e!=NULL){ 
           index = (int)(e-buf[r]); 
           if (index == 0){ 
            printf("%s ", buf[r]) ; 
           } 
          } 
         } 
         printf(">"); 
         printf("<"); 
         for(r = 0; r < j; r++) 
         { 
          int index; 
          e = strchr(buf[r],'C'); 
          if (e!=NULL){ 
           index = (int)(e-buf[r]); 
           if (index == 0){ 
            printf("%s ", buf[r]) ; 
           } 
          } 
         } 
         printf(">"); 
         printf("<"); 
         for(r = 0; r < j; r++) 
         { 
          int index; 
          e = strchr(buf[r],'D'); 
          if (e!=NULL){ 
           index = (int)(e-buf[r]); 
           if (index == 0){ 
            printf("%s ", buf[r]) ; 
           } 
          } 
         } 
         printf(">\n"); 
         switch (s){ 
          case 0: 
           close(parent_child[1]); 
           close(parent_child[0]); 
           close(child_parent[0]); 
           buffer[0] = buf[0]; 
           printf("child %d: %s", s+1, buffer[0]); 
           write(child_parent[1], &buffer[0], strlen(buffer[0])); 
           close(child_parent[1]); 
           break; 
          case 1: 
           close(parent_child2[1]); 
           close(parent_child2[0]); 
           close(child2_parent[0]); 
           buffer[0] = buf[0]; 
           printf("child %d: %s", s+1, buffer[0]); 
           write(child2_parent[1], &buffer[0], strlen(buffer[0])); 
           close(child2_parent[1]); 
           break; 
          case 2: 
           close(parent_child3[1]); 
           close(parent_child3[0]); 
           close(child3_parent[0]); 
           buffer[0] = buf[0]; 
           printf("child %d: %s", s+1, buffer[0]); 
           write(child3_parent[1], &buffer[0], strlen(buffer[0])); 
           close(child3_parent[1]); 
           break; 
          case 3: 
           close(parent_child4[1]); 
           close(parent_child4[0]); 
           close(child4_parent[0]); 
           buffer[0] = buf[0]; 
           printf("child %d: %s", s+1, buffer[0]); 
           write(child4_parent[1], &buffer[0], strlen(buffer[0])); 
           close(child4_parent[1]); 
           break; 
         } 
    } 
    void parentFunction(){ 
    
           switch (s){ 
            case 0: 
             close(child_parent[1]); 
             close(parent_child[1]); 
             close(parent_child[0]); 
             read(child_parent[0],&buffer[0], sizeof(buffer[0])); 
             printf("parent: child %d played %s", s+1, buffer[0]); 
             close(child_parent[0]); 
             break; 
            case 1: 
             close(child2_parent[1]); 
             close(parent_child2[1]); 
             close(parent_child2[0]); 
             read(child2_parent[0],&buffer[0], sizeof(buffer[0])); 
             printf("parent: child %d played %s", s+1, buffer[0]); 
             close(child2_parent[0]); 
             break; 
            case 2: 
             close(child3_parent[1]); 
             close(parent_child3[1]); 
             close(parent_child3[0]); 
             read(child3_parent[0],&buffer[0], sizeof(buffer[0])); 
             printf("parent: child %d played %s", s+1, buffer[0]); 
             close(child3_parent[0]); 
             break; 
            case 3: 
             close(child4_parent[1]); 
             close(parent_child4[1]); 
             close(parent_child4[0]); 
             read(child4_parent[0],&buffer[0], sizeof(buffer[0])); 
             printf("parent: child %d played %s", s+1, buffer[0]); 
             close(child4_parent[0]); 
             break; 
           } 
    } 
    int main(int argc, char *argv[]) 
    { 
        int ch; 
        ssize_t rread; 
        char *line = NULL; 
        size_t len = 0; 
        while (rread = getdelim(&line, &len, '\0', stdin) != -1) { 
        } 
    
        array[i] = strtok(line," "); 
    
        while(array[i]!=NULL) 
        { 
         array[++i] = strtok(NULL," "); 
        } 
    
        int childlimit = 4; 
        int childpids[childlimit]; 
        int currpid; 
    
    
        if (pipe(child_parent) == 0 && pipe(parent_child) == 0 && pipe(child2_parent) == 0 && pipe(parent_child2) == 0 && pipe(child3_parent) == 0 && pipe(parent_child3) == 0 && pipe(child4_parent) == 0 && pipe(parent_child4) == 0) 
        { 
         for(s=0; s<childlimit; s++){ 
         switch(currpid = fork()){ 
         case 0: 
         printf("Child : %d, pid %d : ", s+1, getpid()); 
         childFunction(); 
         break; 
         case -1: 
         printf("Error when forking\n"); 
         return 1; 
         default: 
         // in the father 
         childpids[s] = currpid; 
         parentFunction(); 
         break; 
         } 
          } 
        //wait for all child created to die 
        waitpid(-1, NULL, 0); 
        } 
    } 
    
  • +1

    あなたは '機能' と呼ばれるこれらの事を聞いたことがありますか?コードを明確にするのに便利です。メイン関数で子プロセスを処理するコードが多すぎます。プロセス管理を 'main()'にしておきます。文字列処理とI/O操作を、子プロセスでのみ実行される関数に委譲します。あなたは実際に子供の中で十分なファイル記述子を閉じているわけではありません。親がその子に書き込む必要がある場合は、親にあまりにも多くのファイル記述子をクローズしています。親が子どもに書き込む必要がない場合、なぜ親から子へのパイプで気になりますか? –

    +0

    @ JonathanLeffler、コードを親と子のコードを別の関数に変更しました。私の実装では、子への親の書き込みが必要ですが、この時点では問題のためにまだ開発されていません。 –

    +0

    関数のループ制御にグローバル変数 'i'を使用するのは災害です。グローバル変数が必要な場合もあります。グローバル変数が必要な場合は、それらを使用する必要があります。ほとんどの人は、そうではありません。そうでないときは、使用しないでください。一文字のグローバル変数名はあまり適切ではありません。 (これは、実行したように必要な各関数で 'i'の定義を繰り返すほうがはるかに優れています。)これにより、コードを非常に解析しにくくなります。あなたの文字列読み取りループは最後の '行'(ヌルで終了する '行')のみを保持します。私はそれが単一の操作でファイル全体をスラッピングする方法だと思います。 –

    答えて

    1

    、あなたの変数から脱出しようとしている配列があります。あなたがこれらの変数の4つのセットを持っているとき、それは悲しいです。

    コードには多くの多くの問題がありました。これは総書き換えです。エラーはstderrに報告されます。ほとんどのシステムコールがチェックされます。読み込まれたデータの診断出力があります。文字列を空白の単語に分割する関数split_string()があります。これは、親コンポーネントと子コンポーネントの両方で使用されます。子供はもはや文字列データにアクセスすることができなくなりました - すべてのグローバル変数はなくなりました。

    コードはまだ最適ではありません。子供を始める前にすべてのパイプを開く必要は特にありません。プロセスは同期しています。各子供のためのパイプを順番に作ることは実現可能であり、賢明であろう。それが起きると、各子は利用可能なパイプ記述子の4分の1しか閉じません。

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <sys/wait.h> 
    #include <unistd.h> 
    
    enum { MAX_KIDS = 4 }; 
    enum { LIST_SIZE = 1024 }; 
    enum { MAX_WORDS = LIST_SIZE/3 }; 
    
    static int split_string(char *data, char *words[], int max_words) 
    { 
        int num_words = 0; 
        char *src = data; 
        char *token; 
        while ((token = strtok(src, " \n\t")) != NULL) 
        { 
         words[num_words++] = token; 
         if (num_words >= max_words) 
          break; 
         src = NULL; 
        } 
        return num_words; 
    } 
    
    static void childFunction(int s, int f_pipe[2], int t_pipe[2]) 
    { 
        srand(getpid()); 
        close(f_pipe[1]); 
        close(t_pipe[0]); 
        char data[LIST_SIZE]; 
        int nbytes; 
        if ((nbytes = read(f_pipe[0], data, sizeof(data))) <= 0) 
        { 
         fprintf(stderr, "child %d (PID %d): failed to read pipe\n", s, (int)getpid()); 
         exit(1); 
        } 
        data[nbytes] = '\0'; 
        close(f_pipe[0]); 
    
        char *words[MAX_WORDS]; 
        int num_words = split_string(data, words, MAX_WORDS); 
        char *word = words[rand() % num_words]; 
        int len = strlen(word); 
        if (write(t_pipe[1], word, len) != len) 
        { 
         fprintf(stderr, "child %d (PID %d): failed to write [%s] to pipe\n", s, (int)getpid(), word); 
         exit(1); 
        } 
        close(t_pipe[1]); 
        exit(0); 
    } 
    
    static void parentFunction(int s, int c_pid, int t_pipe[2], int f_pipe[2], char *words[], int max_words) 
    { 
        close(t_pipe[0]); 
        close(f_pipe[1]); 
    
        char buffer[LIST_SIZE]; 
        char *data = buffer; 
        const char *pad = ""; 
        for (int i = s; i < max_words; i += MAX_KIDS) 
        { 
         int n = snprintf(data, (size_t)(buffer + sizeof(buffer) - data), "%s%s", pad, words[i]); 
         data += n; 
         pad = " "; 
        } 
        printf("Send [%s] to child %d\n", buffer, s); 
    
        /* Write list of words to child */ 
        int nbytes = data - buffer; 
        if (write(t_pipe[1], buffer, nbytes) != nbytes) 
        { 
         fprintf(stderr, "parent: failed to write to child %d (PID %d)\n", s, c_pid); 
         exit(1); 
        } 
        close(t_pipe[1]); 
    
        /* Read selected word from child */ 
        nbytes = read(f_pipe[0], buffer, sizeof(buffer)); 
        if (nbytes <= 0) 
        { 
         fprintf(stderr, "parent: failed to read from child %d (PID %d)\n", s, c_pid); 
         exit(1); 
        } 
        buffer[nbytes] = '\0'; 
        close(f_pipe[0]); 
    
        printf("parent: child %d (PID %d) played %s\n", s, c_pid, buffer); 
    } 
    
    int main(void) 
    { 
        ssize_t rread; 
        char *line = NULL; 
        size_t len = 0; 
        if ((rread = getdelim(&line, &len, '\0', stdin)) == -1) 
        { 
         fprintf(stderr, "Unexpected EOF on standard input\n"); 
         return 1; 
        } 
    
        printf("line [%s]\n", line); 
    
        char *wordlist[MAX_WORDS]; 
        int num_words = split_string(line, wordlist, MAX_WORDS); 
    
        printf("Word list:"); 
        int i; 
        for (i = 0; i < num_words; i++) 
        { 
         if (i % 10 == 0 && i > 0) 
          printf("%10s", ""); 
         printf(" %2d [%s]", i, wordlist[i]); 
         if (i % 10 == 9) 
          putchar('\n'); 
        } 
        if (i % 10 != 0) 
         putchar('\n'); 
        printf("%d words\n", i); 
    
        for (int kid = 0; kid < MAX_KIDS; kid++) 
        { 
         printf("Words for child %d:", kid); 
         for (int word = kid; word < i; word += MAX_KIDS) 
          printf(" [%s]", wordlist[word]); 
         putchar('\n'); 
        } 
    
        int child_parent[MAX_KIDS][2]; 
        int parent_child[MAX_KIDS][2]; 
    
        for (int i = 0; i < MAX_KIDS; i++) 
        { 
         if (pipe(child_parent[i]) != 0 || pipe(parent_child[i]) != 0) 
         { 
          fprintf(stderr, "failed to create pipes for child %d\n", i); 
          exit(1); 
         } 
        } 
    
        for (int s = 0; s < MAX_KIDS; s++) 
        { 
         int currpid = fork(); 
         if (currpid < 0) 
         { 
          fprintf(stderr, "Error when forking\n"); 
          exit(1); 
         } 
         else if (currpid == 0) 
         { 
          printf("Child : %d, pid %d:\n", s, getpid()); 
          childFunction(s, parent_child[s], child_parent[s]); 
         } 
         else 
          parentFunction(s, currpid, parent_child[s], child_parent[s], wordlist, num_words); 
        } 
    
        int corpse; 
        int status; 
        while ((corpse = waitpid(-1, &status, 0)) > 0) 
         printf("PID %d died with exit status 0x%.4X\n", corpse, status); 
    } 
    

    データファイルを考える:プログラムからの

    S2 SA SQ S8 S3 S6 S5 SJ S9 S7 H2 SK H9 S4 C7 
    ST H6 H4 C5 HK HA HJ C8 HT H8 H7 CA H5 C6 CQ 
    C4 H3 CK C9 CJ HQ D8 CT C3 C2 DQ DT DA D4 D7 
    D2 D5 D6 D3 D9 
    

    1の出力例は次のとおりです。

    line [S2 SA SQ S8 S3 S6 S5 SJ S9 S7 H2 SK H9 S4 C7 
    ST H6 H4 C5 HK HA HJ C8 HT H8 H7 CA H5 C6 CQ 
    C4 H3 CK C9 CJ HQ D8 CT C3 C2 DQ DT DA D4 D7 
    D2 D5 D6 D3 D9 
    ] 
    Word list: 0 [S2] 1 [SA] 2 [SQ] 3 [S8] 4 [S3] 5 [S6] 6 [S5] 7 [SJ] 8 [S9] 9 [S7] 
          10 [H2] 11 [SK] 12 [H9] 13 [S4] 14 [C7] 15 [ST] 16 [H6] 17 [H4] 18 [C5] 19 [HK] 
          20 [HA] 21 [HJ] 22 [C8] 23 [HT] 24 [H8] 25 [H7] 26 [CA] 27 [H5] 28 [C6] 29 [CQ] 
          30 [C4] 31 [H3] 32 [CK] 33 [C9] 34 [CJ] 35 [HQ] 36 [D8] 37 [CT] 38 [C3] 39 [C2] 
          40 [DQ] 41 [DT] 42 [DA] 43 [D4] 44 [D7] 45 [D2] 46 [D5] 47 [D6] 48 [D3] 49 [D9] 
    50 words 
    Words for child 0: [S2] [S3] [S9] [H9] [H6] [HA] [H8] [C6] [CK] [D8] [DQ] [D7] [D3] 
    Words for child 1: [SA] [S6] [S7] [S4] [H4] [HJ] [H7] [CQ] [C9] [CT] [DT] [D2] [D9] 
    Words for child 2: [SQ] [S5] [H2] [C7] [C5] [C8] [CA] [C4] [CJ] [C3] [DA] [D5] 
    Words for child 3: [S8] [SJ] [SK] [ST] [HK] [HT] [H5] [H3] [HQ] [C2] [D4] [D6] 
    Send [S2 S3 S9 H9 H6 HA H8 C6 CK D8 DQ D7 D3] to child 0 
    Child : 0, pid 89366: 
    parent: child 0 (PID 89366) played HA 
    Send [SA S6 S7 S4 H4 HJ H7 CQ C9 CT DT D2 D9] to child 1 
    Child : 1, pid 89367: 
    parent: child 1 (PID 89367) played S4 
    Send [SQ S5 H2 C7 C5 C8 CA C4 CJ C3 DA D5] to child 2 
    Child : 2, pid 89368: 
    parent: child 2 (PID 89368) played C5 
    Send [S8 SJ SK ST HK HT H5 H3 HQ C2 D4 D6] to child 3 
    Child : 3, pid 89369: 
    parent: child 3 (PID 89369) played D6 
    PID 89368 died with exit status 0x0000 
    PID 89367 died with exit status 0x0000 
    PID 89366 died with exit status 0x0000 
    PID 89369 died with exit status 0x0000 
    
    +0

    それは私が必要とするものです。ありがとうございました。 +1 –

    関連する問題