2016-03-28 35 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; 
}