2014-11-01 136 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