2017-10-18 1 views
1

두 개의 명령을 묻는 간단한 파이프 프로그램을 작성한 후 프로그램을 bash에 cmd1 | cmd2으로 입력 한 것처럼 실행합니다. 그런 다음 명령 중 하나가 quit이 될 때까지 반복하고 묻습니다.wait (NULL)로 인해 실행이 중지되는 것 같습니다.

이미이 정도 작성했습니다 : 나는 그것을 실행하고 입력하면

#include<iostream> 
#include<string> 
#include<sys/types.h> 
#include<sys/wait.h> 
#include<string.h> 
#include<unistd.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include<signal.h> 

using namespace std; 

int main(int argc, char *argv[]) 
{ 
    int pid1, pid2, errchk; 
    int pip[2]; 
    char cmd1[128]; 
    char cmd2[128]; 
    int i = 0; 
    int status; 

    errchk = pipe(pip);//make pipe 
    if(errchk == -1)//check for error in pipe 
    { 
     perror("pipe"); 
     exit(1); 
    } 

    while(i<3) 
    { 
     i++; 
     //Enter commands here 
     cout<<"Enter cmd1: "; 
     cin>>cmd1; 
     cout<<"Enter cmd2: "; 
     cin>>cmd2; 
     //if a command is quit... quit 
     if(strcmp(cmd1,"quit")==0 || strcmp(cmd2,"quit") == 0) 
     { 
      cout<<"Quitting...\n"; 
      exit(1); 
     } 

     pid1 = fork(); 
     cout<<"first fork makes pids: "<<pid1<<endl; 
     if(pid1 < 0) 
     { 
      perror("fork"); 
      exit(1); 
     } 

     else if(pid1 == 0) //MAIN CHILD 
     { 
      cout<<"In main child with pid: "<<pid1<<endl; 
      pid2 = fork(); 
      cout<<"second fork makes pids: "<<pid2<<endl; 
      if(pid2 == 0)//SUB CHILD 2 to run cmd2 
      { 
       cout<<"In child of second fork"<<endl; 
       close(0); 
       close(pip[1]); 
       dup(pip[0]); 
       execvp(cmd2,argv);//execute command2 and die 
      } 
      else if(pid2 > 0)//SUB CHILD 1 to run cmd1 
      { 
       cout<<"In parent of second fork"<<endl; 
       close(1); 
       close(pip[0]); 
       dup(pip[1]); 
       execvp(cmd1,argv);//execute command1 and die 
      } 
     } 
     else if(pid1 > 0) //MAIN PARENT 
     { 
      wait(NULL);//wait for cmd1 
      wait(NULL);//wait for cmd2 
      cout<<"DONE executing"<<endl; //keep going 
     } 
    } 
    return 0; 
} 

lswc 내가 얻을 출력은 다음과 같습니다

Enter cmd1: ls 
Enter cmd2: wc 
first fork makes pids: 5785 
first fork makes pids: 0 
In main child with pid: 0 
second fork makes pids: 5786 
In parent of second fork 
second fork makes pids: 0 
In child of second fork 
DONE executing 
     5  5  54 

내가 가진 가장 큰 문제는 I Done executingls|wc 뒤에 오는 것이 좋습니다. wait(NULL)이 작동하지 않지만 확실하지 않다고 생각합니다.

알려 주시기 바랍니다. 고마워요.

+1

손주를 기다릴 수 없습니다. child1은 child2를 기다려야 만한다. –

+0

악의적 인 사용자가 공백없이 긴 문자열을 입력하면 정의되지 않은 동작이 발생하여'cin >> cmd1;'과'cin >> cmd2;'행이 오버플로 할 수있다. 이것은 C++이므로'char [128]'가 아니라'std :: string'을 사용하십시오. – aschepler

+0

execvp는 문자열과 작동하지 않으므로 char을 사용해야합니다. – sshulgan

답변

1

당신은이 :

parent 
    1. child1 
    2. child2 
    2. exec() 
    1. exec() 

당신이 자식 1에 간부 인

는, 자식 2는 초기화하기 위해서 다시 부모가됩니다, 당신은 더 이상 종료 자식 2를 기다릴 수 없습니다. 모양 - 모두 코드 같은 (일부 주석을 수행하기 위해 리팩토링과 함께, 자신의 코드에 기초를 두는

parent 
    1. child1 
    1. exec() 
    2. child2 
    2. exec() 
wait() x 2 

:

그래서 우리처럼 보이는 뭔가를 얻기 위해 리팩토링의 조금을 할 필요가 - 라인) :

#include<iostream> 
#include<string> 
#include<sys/types.h> 
#include<sys/wait.h> 
#include<string.h> 
#include<unistd.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include<signal.h> 

using namespace std; 

int main(int argc, char *argv[]) 
{ 
    int pid1, pid2, errchk; 
    int pip[2]; 
    char cmd1[128]; 
    char cmd2[128]; 
    int status; 

    while(true) 
    { 
     errchk = pipe(pip);//make pipe 
     if(errchk == -1)//check for error in pipe 
     { 
      perror("pipe"); 
      exit(1); 
     } 

     //Enter commands here 
     cout<<"Enter cmd1: "; 
     cin>>cmd1; 
     cout<<"Enter cmd2: "; 
     cin>>cmd2; 
     //if a command is quit... quit 
     if(strcmp(cmd1,"quit")==0 || strcmp(cmd2,"quit") == 0) 
     { 
      cout<<"Quitting...\n"; 
      exit(1); 
     } 

     pid1 = fork(); 
     cout<<"first fork makes pids: "<<pid1<<endl; 
     if(pid1 < 0) 
     { 
      perror("fork"); 
      exit(1); 
     } 
     if (pid1 == 0) // in child 
     { 
      cout<<"In child of first fork"<<endl; 
      close(pip[0]); // close read-end of pipe 
      close(0); // close stdin 
      close(1); // close stdout 
      dup2(pip[1], 1); // write-end of pipe is stdout of cmd1 
      argv[0] = cmd1; // make it look like the command in the ps output 
      execvp(cmd1,argv);//execute command1 and die 
      fprintf(stderr, "execvp(1): `%s': %s\n", cmd1, strerror(errno)); 
      return 0; 
     } 
     pid2 = fork(); 
     cout<<"second fork makes pids: "<<pid2<<endl; 
     if (pid2 < 0) 
     { 
      perror("fork2"); 
      exit(1); 
     } 
     if (pid2 == 0) 
     { 
      cout<<"In child of second fork"<<endl; 
      close(pip[1]); // close write-end of pipe 
      close(0); // close stdin 
      dup2(pip[0], 0); // read-end of pipe is stdin of cmd2 
      argv[0] = cmd2; // update ps output 
      execvp(cmd2,argv);//execute command2 and die 
      fprintf(stderr, "execvp(1): `%s': %s\n", cmd2, strerror(errno)); 
      return 0; 
     } 
     if(pid1 > 0) //MAIN PARENT 
     { 
      // close remaining pipe handles in parent 
      close(pip[0]); 
      close(pip[1]); 
      wait(0);//wait for one command to run 
      wait(0);//wait for a second command to run 
      cout<<"DONE executing"<<endl; //keep going 
     } 
    } 
    return 0; 
} 
+0

예, 지금 당신이하고있는 것을 깨달았습니다. 원래 대답에서 오류가있었습니다. 나는 대답을 편집 할 필요가있다 – Petesh

+0

나는 파이프 위의 while 루프를 움직여 그 상태를'true'로 만들었다. 그래서 연속적으로 2 개의 명령을 요구하고, 실행 한 다음 2 개 더 묻는다. 그러나 처음 실행했을 때 'ls'와'wc'를 넣음으로써'0 0 0'을 보여주고 두번째로 올바른 데이터를 내기 시작합니까? 왜 어떤 아이디어? – sshulgan

+0

예, 첫 번째 라운드에서만 작동 했으므로 while 루프 내부에서 파이프를 움직이는 것이 내 변경 사항을 수정했습니다. 왜 처음에'0 0 0'을 얻었는지 모르겠다 - 만약 execvp가 실패했다면 나는 그것을 보았을 것이고 그래서 나는 execvps와 에러 메시지를 보여주기 위해 추가적인 에러 체크를했다. 그럴 경우. – Petesh

관련 문제