2017-10-18 3 views
1

2つのコマンドを要求する単純なパイププログラムを作成していて、プログラムが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

:あなたがchild1の中でexecした場合

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

、child2のはinitに再ペアレントます、そしてあなたは、もはや終了するchild2のを待つことはできません。そっくりコードのようなもの(いくつかのコメントでを達成するためにリファクタリングして、独自のコードでこれを基づか

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ループを移動し、その条件を「真」にして、連続して2つのコマンドを要求して実行し、2つ以上を求めることができます...しかし、 'ls'と' wc'を入れて '0 0 0'を表示し、次に2番目に正しいデータを与えるようになりますか?理由は何ですか? – sshulgan

+0

ええ、最初のラウンドでしか動かないので、whileループの中でパイプを動かすことは私の変更を修正したものです。私は最初に '0 0 0'を得ているのか分からない - もしexecvpが失敗したら、私は先に行ってエラーメッセージを表示するために両方のexecvpsの後に追加のエラーチェックをしたその場合は。 – Petesh

関連する問題