2016-03-28 75 views
1

我想實現這樣的場景:並行處理方案實現停留在等待輸入

parallel process scenario

其中ls -lcat /etc/group進程中運行並行,並tr /a-z/ /A-Z/需要從他們組合的輸入。然後將它們的大寫版本轉移到cat -ngrep Z(它們也應該並行運行)。 cat -ngrep Z應輸出到stdout。

所以在stdoutput,

(ls -l ; cat /etc/group) | tr /a-z/ /A-Z/ | cat -n

(ls -l ; cat /etc/group) | tr /a-z/ /A-Z/ | grep A

應打印。

我寫這個程序來實現我的目標:

#include<stdio.h> 
#include<unistd.h> 
#include<wait.h> 

int main() 
{ 
    int dummy, i; 
    size_t size = 0; 
    int pipe1[2]; 
    int pipe2[2]; 
    int pipe3[2]; 
    char* lsargs0[] = {"/bin/ls", "-l", NULL}; 
    char* lsargs1[] = {"cat", "/etc/group", NULL}; 
    char* lsargs2[] = {"tr", "/a-z/", "/A-Z/", NULL}; 
    char* lsargs3[] = {"cat", "-n", NULL}; 
    char* lsargs4[] = {"grep", "A", NULL}; 
    char** am[]  = {lsargs0, lsargs1, lsargs2, lsargs3, lsargs4}; 
    char buf[4096]; 

    pipe(pipe1); 
    pipe(pipe2); 
    pipe(pipe3); 

    for (i = 0 ; i < 5 ; i++) 
    { 
     pid_t pid = fork(); 

     if (pid == 0) 
     { 
      if (i == 0 || i == 1) // ls -l & cat 
      { 
       // 0 -> stdin, 1 -> pipe write end 
       close(pipe2[0]); 
       close(pipe2[1]); 

       close(pipe3[0]); 
       close(pipe3[1]); 

       close(pipe1[0]); 
       dup2(pipe1[1], 1); 
       close(pipe1[1]); 

       execvp(am[i][0], am[i]); 
      } 
      else if (i == 2) //TR AZ AZ 
      { 
       int extraPipe[2]; 
       pipe(extraPipe); 

       int forkMaster = fork(); 

       if (forkMaster != 0) 
       { 
        printf("TR az AZ fork parent\n"); 
        //parent 
        close(pipe2[0]); 
        close(pipe2[1]); 

        close(pipe3[0]); 
        close(pipe3[1]); 

        close(pipe1[1]); 
        dup2(pipe1[0], 0); 
        close(pipe1[0]); 

        close(extraPipe[0]); 
        dup2(extraPipe[1], 1); 
        close(extraPipe[1]); 

        //waitpid(forkMaster, &dummy, WNOHANG); 
        //wait(&dummy); 

        execvp(am[i][0], am[i]); 
       } 
       else 
       { 
        printf("TR az AZ child\n"); 
        //child 
        read(extraPipe[0], buf, 4095); 
        //printf("%s\n", buf); 

        write(pipe2[1], buf, size); 
        write(pipe3[1], buf, size); 
        close(pipe1[1]); 
        close(pipe1[0]); 

        close(extraPipe[0]); 
        close(extraPipe[1]); 

        close(pipe2[0]); 
        close(pipe2[1]); 

        close(pipe3[0]); 
        close(pipe3[1]); 
        break; 
       } 
      } 
      else if (i == 3) // cat -n 
      { 
       close(pipe1[0]); 
       close(pipe1[1]); 

       close(pipe3[0]); 
       close(pipe3[1]); 

       close(pipe2[1]); 
       dup2(pipe2[0], 0); 
       close(pipe2[0]); 

       execvp(am[i][0], am[i]); 
      } 
      else if (i == 4) //grep Z 
      { 
       close(pipe1[0]); 
       close(pipe1[1]); 

       close(pipe2[0]); 
       close(pipe2[1]); 

       close(pipe3[1]); 
       dup2(pipe3[0], 0); 
       close(pipe3[0]); 

       execvp(am[i][0], am[i]); 
      } 
      break; 
     } 
      //DON'T FORGET TO CLOSE PIPES ON PARENT 
     else if (i == 4) 
     { 
      close(pipe1[0]); 
      close(pipe1[1]); 

      close(pipe2[0]); 
      close(pipe2[1]); 

      close(pipe3[0]); 
      close(pipe3[1]); 
     } 
    } 
    for (i = 0 ; i < 5 ; i++) 
    { 
     wait(&dummy); 
    } 
    return 0; 
} 

但在read(extraPipe[0], buf, 4096);行程序stucks。我究竟做錯了什麼?你可以幫我嗎?

+0

'small.c:97:29:error:'n'may be uninitialized ...'你編譯的代碼作爲例子嗎?發佈之前您需要測試它。 – jdarthenay

+0

我用gcc成功編譯過。但是對於你,我把你的編譯器錯誤的那一行移開了,你能再試一次嗎? –

+0

什麼是您使用的編譯命令?我推薦至少'-Wall',你會被警告你的varriable沒有初始化(這會導致未定義的行爲)。 – jdarthenay

回答

0

兩個進程i == 2仍在等待對方。我後退了一些close(),它似乎正常工作。還需要loop用於複製過程和exit(0);而不是break;

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <wait.h> 

int main() 
{ 
    int dummy, i; 
    size_t size = 0; 
    int pipe1[2]; 
    int pipe2[2]; 
    int pipe3[2]; 
    char* lsargs0[] = {"/bin/ls", "-l", NULL}; 
    char* lsargs1[] = {"cat", "/etc/group", NULL}; 
    char* lsargs2[] = {"tr", "/a-z/", "/A-Z/", NULL}; 
    char* lsargs3[] = {"cat", "-n", NULL}; 
    char* lsargs4[] = {"grep", "A", NULL}; 
    char** am[]  = {lsargs0, lsargs1, lsargs2, lsargs3, lsargs4}; 
    char buf[4096]; 

    pipe(pipe1); 
    pipe(pipe2); 
    pipe(pipe3); 

    for (i = 0 ; i < 5 ; i++) 
    { 
     pid_t pid = fork(); 
     /*if (pid > 0) 
      printf("pid %d = %ld\n", i, (long) pid);*/ 

     if (pid == 0) 
     { 
      if (i == 0 || i == 1) // ls -l & cat 
      { 
       // 0 -> stdin, 1 -> pipe write end 
       close(pipe2[0]); 
       close(pipe2[1]); 

       close(pipe3[0]); 
       close(pipe3[1]); 

       close(pipe1[0]); 
       dup2(pipe1[1], 1); 
       close(pipe1[1]); 

       execvp(am[i][0], am[i]); 
      } 
      else if (i == 2) //TR AZ AZ 
      { 
       int extraPipe[2]; 
       pipe(extraPipe); 

       int forkMaster = fork(); 

       if (forkMaster != 0) 
       { 
        printf("TR az AZ fork parent\n"); 
        //parent 
        close(pipe2[0]); 
        close(pipe2[1]); 

        close(pipe3[0]); 
        close(pipe3[1]); 

        close(pipe1[1]); 
        dup2(pipe1[0], 0); 
        close(pipe1[0]); 

        close(extraPipe[0]); 
        dup2(extraPipe[1], 1); 
        close(extraPipe[1]); 

        //waitpid(forkMaster, &dummy, WNOHANG); 
        //wait(&dummy); 

        execvp(am[i][0], am[i]); 
       } 
       else 
       { 
        printf("TR az AZ child\n"); 
        //child 
        close(pipe1[1]); 
        close(pipe1[0]); 
        close(pipe2[0]); 
        close(pipe3[0]); 
        fprintf(stderr, "Line %d\n", __LINE__); 
        close(extraPipe[1]); 
        do 
        { 
         size = read(extraPipe[0], buf, 4095); 
         if (size > 0) 
         { 
          write(pipe2[1], buf, size); 
          write(pipe3[1], buf, size); 
         } 
        } while (size > 0); 
        fprintf(stderr, "Line %d\n", __LINE__); 
        //printf("%s\n", buf); 


        close(extraPipe[0]); 
        close(pipe2[1]); 
        close(pipe3[1]); 

        exit(0); 

       } 
      } 
      else if (i == 3) // cat -n 
      { 
       close(pipe1[0]); 
       close(pipe1[1]); 

       close(pipe3[0]); 
       close(pipe3[1]); 

       close(pipe2[1]); 
       dup2(pipe2[0], 0); 
       close(pipe2[0]); 

       execvp(am[i][0], am[i]); 
      } 
      else if (i == 4) //grep A 
      { 
       close(pipe1[0]); 
       close(pipe1[1]); 

       close(pipe2[0]); 
       close(pipe2[1]); 

       close(pipe3[1]); 
       dup2(pipe3[0], 0); 
       close(pipe3[0]); 

       execvp(am[i][0], am[i]); 
      } 
      break; 
     } 
      //DON'T FORGET TO CLOSE PIPES ON PARENT 
     else if (i == 4) 
     { 
      close(pipe1[0]); 
      close(pipe1[1]); 

      close(pipe2[0]); 
      close(pipe2[1]); 

      close(pipe3[0]); 
      close(pipe3[1]); 
     } 
    } 
    for (i = 0 ; i < 5 ; i++) 
    { 
     wait(&dummy); 
    } 
    return 0; 
}