2014-11-01 3 views
0

은 안녕하세요 저는 파이프C 여러 파이프 파이프 및 문제

나는 이미 작업 플렉스 프로그램이 그래서 프로그램 같은 쉘을 개발해야

과 표현의 사용을 잃은 비트에 공급되는거야 이 기능

편집

내가 함수 내에서 파이프를 선언 않았다하지만 난 여전히 여기에 같은 문제 가 데이브 에 의해 지적

내가 잠시 이미에 붙어되는 한 기능에 대한 업데이트입니다 예쁘게 파이프를 닫지 않는 것 같아. 두 번째 포크는 항상 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 

하지만3210 난 혼란은 그

ls | grep a > test 

내가 터미널이 아닌 파일에 넣어 출력을 얻을 완전한 잘못된

exemple 간다까지의 경우

또는 내가

ls | grep a | grep c 
를 사용하는 경우

파이프가 엉망으로 간다. 나는 더 많은 파이프가 필요하다고 생각하지만, 파이프를 만드는 방법을 모른다.

덕분에 모든

편집


은 파이프의 수정 후 내가 대신 파일 에 내가 고양이를했던 LS의 exemple를 위해 더 큰 데이터 로 명령을 시도 않았다고 생각하는 모든 데이터가 파이프에 도착하기 전에 명령이 멈춘 것처럼 보입니다.

+0

어디에서 pp가 정의 되었습니까? 배관을하고있는 것이지만 우리에게 정의를주지는 않았습니다. – dave

+0

pp는 단지 ** int pp [2] ** 뒤에 ** pipe (pp) ** –

답변

1

그래서 내가 마지막 포크 내가 마지막 명령을 확인하고 바로 마지막에 대기 PID를 사용하는 플래그 (F)를 추가 않았다,이 경우 을 발사하기 전에 내 문제는 대기가 호출되고 있었다

그것을

를 고정 추측 여기

아마 코드

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

입니다. 여러분이 지적한 것을 편집했지만 방금 같은 결과를 얻었습니다 –