创建管道 - Unix

时间:2012-07-15 16:50:52

标签: c unix pipe

下面是我试图让它工作的代码......

我期待输出为

OUTPUT from PipeAttempt(args1, args2)

接着是

I am here

OUTPUT from PipeAttempt(args3, args4)

但实际上,我只从PipeAttempt输出(args1,args2);

并且程序等待来自我的输入,当我按下回车键时程序终止

你能告诉我在这里缺少什么吗?

int main () {
    char* args1 [] = {"/usr/bin/head", "/etc/passwd", NULL};
    char* args2 [] = {"/bin/sort", NULL};

    char* args3 [] = {"/bin/cat", "piped.input", NULL}; 
    char* args4 [] = {"/usr/bin/wc", NULL};



    PipeAttempt(args1, args2);

    printf("I am here\n");

    PipeAttempt(args3, args4);


    return 0;

}


void PipeAttempt(char* args1[], char* args2[]) {
    int pfildes[2]; <br>
    pid_t cpid1, cpid2; <br>
    char *envp[] = { NULL };<br>


    if (pipe(pfildes) == -1)    {perror("demo1"); exit(1);}
    if ((cpid1 = fork()) == -1)   {perror("demo2"); exit(1);}
    else if (cpid1 == 0) {        /* child:  "cat a"                      */
          close(pfildes[0]);    /* close read end of pipe               */
          dup2(pfildes[1],1);   /* make 1 same as write-to end of pipe  */
          close(pfildes[1]);    /* close excess fildes                  */

       execve(args1[0], args1, envp);

          perror("demo3");       /* still around?  exec failed           */
          exit(1);             /* no flush                             */ 
        }
    else {                      /* parent:  "/usr/bin/wc"               */
          close(pfildes[1]);    /* close write end of pipe              */
          dup2(pfildes[0],0);   /* make 0 same as read-from end of pipe */
          close(pfildes[0]);    /* close excess fildes                  */

       execve(args2[0], args2, envp);
          perror("demo4");       /* still around?  exec failed           */
          exit(1);          /* parent flushes                       */
        }   
}

2 个答案:

答案 0 :(得分:1)

你的原始父母被exec调用覆盖。所以你只能得到/ usr / bin / head / etc / passwd的输出。 / bin / sort,你没有得到/ bin / cat piped.input | / usr / bin / wc的输出。

程序实际上并没有等你键盘输入。发生了什么事情是没有显示shell提示。父母在孩子面前退出并且提示被shell立即显示(等待父母)并且孩子的输出在此之后出现,这让你认为该程序正在等待用户输入。

这里解决这个问题你可以在函数中分叉另一个子节点,这样就可以有效地为每个函数(PipeAttempt)调用两个子节点来处理管道,在main中你可以等待所有四个子节点完成,这样父节点就可以了最后退出并返回shell提示符。鉴于以下修改后的代码,低于pl。在编译之前包括wait,strlen等的头文件。希望这能解决您的问题。

void PipeAttempt(char* args1[], char* args2[]) ;
int main () {
int i;
char* args1 [] = {"/usr/bin/head", "/etc/passwd", NULL};
char* args2 [] = {"/bin/sort", NULL};

char* args3 [] = {"/bin/cat", "piped.input", NULL}; 
char* args4 [] = {"/usr/bin/wc", NULL};

PipeAttempt(args1, args2);
write(1, "I am here\n", strlen("I am here\n"));
PipeAttempt(args3, args4);
for (i=0; i < 4; i++)
{

    wait(NULL);
}
return 0;
}

void PipeAttempt(char* args1[], char* args2[]) 
{
    int pfildes[2]; 
    pid_t cpid1, cpid2; 
    char *envp[] = { NULL };


    if (pipe(pfildes) == -1)    {perror("demo1"); exit(1);}

    if ((cpid1 = fork()) == -1)   {perror("demo2"); exit(1);}
    else if (cpid1 == 0)
   {        /* child1    */
        close(pfildes[0]);    /* close read end of pipe               */
        dup2(pfildes[1],1);   /* make 1 same as write-to end of pipe  */
        close(pfildes[1]);    /* close excess fildes                  */
        execve(args1[0], args1, envp);
        perror("demo3");       /* still around?  exec failed           */
        exit(1);             /* no flush                             */ 
    }
   else {                      
    /* child2:  "/usr/bin/wc"               */
     if (0==fork())
      {
         close(pfildes[1]);    /* close write end of pipe              */
         dup2(pfildes[0],0);   /* make 0 same as read-from end of pipe */
         close(pfildes[0]);    /* close excess fildes                  */
         execve(args2[0], args2, envp);
         perror("demo4");       /* still around?  */
         exit(1);
      }
//Parent
 close(pfildes[0]); 
 close(pfildes[1]); 
    }   
}

答案 1 :(得分:0)

您的PipeAttempt()函数执行fork / exec - 您如何期望它返回到main函数?