2014-11-01 103 views
0

你好,我是失去了对使用管道碳多重管道管和问题文件描述符

我要开发像程序的外壳,所以我有一个柔性程序已经工作和表达的位都被喂此功能

编辑

如指出由Dave 我没申报的管道里面的功能,但我仍然有同样的问题 所以这里是我已经被卡就可以了,而已经 功能的更新看起来像我没有关闭管道,因为第二叉始终是悬在waitpid函数()

,但我没有尝试关闭的主要过程所有的岔路口和所有孩子的,但第二叉仍挂


int execute(Expression *e , int wait, int fdin,int fdout,int fderror){ 
    int status; 
    pid_t childPID; 
    int fd; 
    int pp[2]; 

    switch (e->type) { 
     case SIMPLE: 
      childPID = fork(); 
      if(childPID >= 0) //fork was successful 
      { 
       if(childPID == 0) //child process 
       { 
        if(fdin != 0){ 
         dup2(fdin,0); 
         close(fdin); 
         if(fdin > 2){ 
          close(fdin +1); 
         } 
        } 
        if(fdout != 0){ 
         dup2(fdout,1); 
         close(fdout); 
         if(fdout > 3){ 
          close(fdout -1); 
         } 
        } 
        if(fderror != 2){ 
         dup2(fderror,2); 
         close(fderror); 
        } 
        status = execvp(e->arguments[0], &e->arguments[0]); 
        perror(e->arguments[0]); 
        exit(1); 
       } 
       else//parent process 
       { 
        if(fdin > 2){ 
         close(fdin);  
         close(fdin +1); 
        } 
        if(fdout > 3){ 
         close(fdout); 
         close(fdout -1);  
        } 

        if(wait == 1){ 
         printf("%s\n","going to wait"); 
         waitpid(childPID, &status, 0); 
        } 
        putchar('\n'); 
        break; 
       } 
      } 
      else// fork failed 
      { 
       perror("fork"); 
      } 
      break; 
     case SEQUENCE: 
      execute(e->gauche,1,fdin,fdout,fderror); 
      execute(e->droite,1,fdin,fdout,fderror); 
      break; 
     case SEQUENCE_ET: 
      execute(e->gauche,0,fdin,fdout,fderror); 
      execute(e->droite,1,fdin,fdout,fderror); 
      break; 
     case SEQUENCE_OU: 
      execute(e->gauche,0,fdin,fdout,fderror); 
      execute(e->droite,1,fdin,fdout,fderror); 
      break; 
     case BG: 
      execute(e->gauche,0,fdin,fdout,fderror); 
      break; 
     case PIPE: 
      if(pipe(pp) < 0){ 
       perror("pipe"); 
       exit(1); 
      } 
      execute(e->gauche,0,fdin,pp[1],fderror); 
      execute(e->droite,1,pp[0],fdout,fderror); 
      break; 
     case REDIRECTION_I: 
      fd = open(e->arguments[0],O_RDONLY, 0666); 
      execute(e->gauche,1,fd,fdout,fderror); 
      break; 
     case REDIRECTION_O: 
      fd = open(e->arguments[0],O_CREAT | O_RDWR, 0666); 
      execute(e->gauche,1,fdin,fd,fderror); 
      break; 
     case REDIRECTION_A: 
      fd = open(e->arguments[0], O_TRUNC | O_CREAT | O_RDWR, 0666); 
      execute(e->gauche,1,fdin,fd,fderror); 
      break; 
     case REDIRECTION_E: 
      fd = open(e->arguments[0], O_CREAT | O_RDWR, 0666); 
      execute(e->gauche,1,fdin,fdout,fd); 
      break; 
     case REDIRECTION_EO: 
      fd = open(e->arguments[0], O_CREAT | O_RDWR, 0666); 
      execute(e->gauche,1,fdin,fd,fd); 
      break; 
     default: 
      return 0; 
      break; 

    } 
    return 0; 


} 

我的问题是,这是运作良好对于简单的命令对应的像

ls | grep a 

OS

ls > test 

,但如果我惹再向上是那张完整的错误

为例

ls | grep a > test 

我得到了穿上终端,而不是在文件

,或者如果我使用

ls | grep a | grep c 

管道变得一团糟我觉得我需要更多的管道来做到这一点,但我不知道如何在飞行中创建管道

感谢所有

编辑


只是想通了,管道修复后,我曾尝试为为例,而不是LS我做猫上的文件 具有更大的数据 的命令是在任何数据进入管道之前看起来像命令停止

+0

pp的定义在哪里?这是做管道的事情,但你没有给我们定义。 – dave 2014-11-01 15:13:35

+0

pp只是一个** int pp [2] **,后面跟着一个**管道(pp)** – 2014-11-01 15:15:14

回答

1

所以我想我固定它

前的最后叉在这种情况下我没有添加标注f,以确定最后的命令,并使用等待PID只是在最后一发射了 我的问题是被称为等待

这里是代码

int execute(Expression *e , int wait, int fdin,int fdout,int fderror, int lastflag){ 
    int status; 
    pid_t childPID; 
    int fd; 
    int pp[2]; 


    switch (e->type) { 
     case SIMPLE: 
      childPID = fork(); 
      if(childPID >= 0) //fork was successful 
      { 
       if(childPID == 0) //child process 
       { 
        if(fdin != 0){ 
         dup2(fdin,0); 
         close(fdin); 
        } 
        if(fdout != 1){ 
         dup2(fdout,1); 
         close(fdout); 
        } 
        if(fderror != 2){ 
         dup2(fderror,2); 
         close(fderror); 
        } 
        for(int i = 3; i <= lastfd; i++){ 
         close(i); 
        } 

        status = execvp(e->arguments[0], &e->arguments[0]); 
        perror(e->arguments[0]); 
        exit(1); 
       } 
       else//parent process 
       { 

        if(wait == 1){ 
         for(int i = 3; i <= lastfd; i++){ 
          close(i); 
         } 
         printf("%s\n","going to wait"); 
         waitpid(childPID, &status, WNOHANG); 
        } 
        putchar('\n'); 
        break; 
       } 
      } 
      else// fork failed 
      { 
       perror("fork"); 
      } 
      break; 
     case SEQUENCE: 
      execute(e->gauche,1,fdin,fdout,fderror,0); 
      execute(e->droite,1,fdin,fdout,fderror,0); 
      break; 
     case SEQUENCE_ET: 
      execute(e->gauche,0,fdin,fdout,fderror,0); 
      execute(e->droite,1,fdin,fdout,fderror,0); 
      break; 
     case SEQUENCE_OU: 
      execute(e->gauche,0,fdin,fdout,fderror,0); 
      execute(e->droite,1,fdin,fdout,fderror,0); 
      break; 
     case BG: 
      execute(e->gauche,0,fdin,fdout,fderror,0); 
      break; 
     case PIPE: 
      if(pipe(pp) < 0){ 
       perror("pipe"); 
       exit(1); 
      } 
      ch_lastfd(pp[1]); 
      execute(e->gauche,0,fdin,pp[1],fderror,0); 
      if(lastflag == 1){ 
       execute(e->droite,1,pp[0],fdout,fderror,0); 
      }else{ 
       execute(e->droite,0,pp[0],fdout,fderror,0); 
      } 
      break; 
     case REDIRECTION_I: 
      fd = open(e->arguments[0],O_RDONLY, 0666); 
      ch_lastfd(fd); 
      execute(e->gauche,1,fd,fdout,fderror,0); 
      break; 
     case REDIRECTION_O: 
      fd = open(e->arguments[0],O_CREAT | O_RDWR, 0666); 
      ch_lastfd(fd); 
      execute(e->gauche,1,fdin,fd,fderror,0); 
      break; 
     case REDIRECTION_A: 
      fd = open(e->arguments[0], O_TRUNC | O_CREAT | O_RDWR, 0666); 
      ch_lastfd(fd); 
      execute(e->gauche,1,fdin,fd,fderror,0); 
      break; 
     case REDIRECTION_E: 
      fd = open(e->arguments[0], O_CREAT | O_RDWR, 0666); 
      ch_lastfd(fd); 
      execute(e->gauche,1,fdin,fdout,fd,0); 
      break; 
     case REDIRECTION_EO: 
      fd = open(e->arguments[0], O_CREAT | O_RDWR, 0666); 
      ch_lastfd(fd); 
      execute(e->gauche,1,fdin,fd,fd,0); 
      break; 
     default: 
      break; 

    } 
    return 0; 


} 

可能不会实现它,如果任何一个有任何想法如何使它更好,我打开感谢技巧的最好方法

1

您正在为所有管道使用全局变量。当你创建ls | grep a时,你的全局管道工作正常。但是当你有多个管道时,你可以将它们用于不同的目的!解决方法是在函数中使用管道创建代码。当你需要一个新的管道时,在那里创建一个,并将正确的文件描述符传递给递归调用execute(这就是为什么你需要fdinfdout参数。

+0

只是对您指出的内容进行了编辑,但仍得到相同的结果 – 2014-11-01 15:31:45