2009-11-07 6 views
9

Unix用のCで単純なシェルを作成しようとしています。私はすべてのコマンドと実行の解析を行うことができましたが、私は配管に問題があります。問題は、2番目のコマンドの入力に正しいパイプを使用していないということです。Cでの配管コマンドの問題

たとえば、「ls | wc」と入力すると、「wc」コマンドの後で一時停止します。これは入力待ちのためです。私は、問題は私がdup2(reading [i]、0)を使用していて、正しいパイプにフックしていないときだと思う。

私はこれが広い質問のビットであることを知っていますが、私が得ることができるポインターがあれば、私はそれを感謝します。ここに新しいプロセスを作成し、それらをパイプしようとするコードがあります。

int fileds[2]; 
    int reading[num_cmds]; 
    int writing[num_cmds]; 

    int p; 
    for(p=0; p < num_cmds; p++) 
    { 
     reading[p] = -1; 
     writing[p] = -1; 
    } 

    int j; 
    for(j=0; j < num_cmds-1; j++) //Create pipes for commands 
    { 
     int fileds[2]; 
     pipe(fileds); 
     reading[j+1] = fileds[0]; 
     writing[j] = fileds[1]; 
    } 

    int i = 0; 
    for(i = 0; i < num_cmds;i++) 
    {   
     cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); //Get command and args 

     pid_t childpid; 
     int status; 
     childpid=fork(); 

     if (childpid >= 0) 
     { 
      if (childpid == 0) 
      {    
       if(writing[i] != -1) 
       { 
        dup2(writing[i],1); 
        close(writing[i]); 
       } 

       if(reading[i] != -1) 
       { 
        dup2(reading[i],0); 
        close(reading[i]); 
       } 

       int h; 
       for(h = 0; h < num_cmds; h++) 
       { 
        close(writing[h]); 
        close(reading[h]); 
       } 

       if(execvp(cmd_args[0],cmd_args) == -1) 
       { 
        perror("Problem with command"); 
        exit(0); 
       } 
      } 
      else 
      { 
       wait(&status); 
       int m; 
       for(m = 0; m < num_cmds; m++) 
       { 
        if(writing[m] != -1) close(writing[m]); 
        if(reading[m] != -1) close(reading[m]); 
       } 
      } 
     } 
     else 
     { 
      perror("fork"); 
      continue; 
     } 


     input_file[0] = 0; 
     output_file[0] = 0; 
     run_bg = 0; 
    } 

} 



UPDATE:私は、リチャードのおかげでそれを把握することができました。これは、ファイル記述子を間違った順序で閉じて、まったく閉じないという組み合わせでした。ここに作業コードがあります。

int fileds[2]; 
    int reading[num_cmds]; 
    int writing[num_cmds]; 

    int p; 
    for(p=0; p < num_cmds; p++) 
    { 
     reading[p] = -1; 
     writing[p] = -1; 
    } 

    int j; 
    for(j=0; j < num_cmds-1; j++) 
    { 
     int fileds[2]; 
     pipe(fileds); 
     reading[j+1] = fileds[0]; 
     writing[j] = fileds[1]; 
    } 

    int i = 0; 
    for(i = 0; i < num_cmds;i++) 
    {   
     cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); 

     pid_t childpid; 
     int status; 
     childpid=fork(); 

     if (childpid >= 0) 
     { 
      if (childpid == 0) 
      {    
       if(writing[i] != -1) 
       { 
        close(1); 
        dup2(writing[i],1); 
       } 

       if(reading[i] != -1) 
       { 
        close(0); 
        dup2(reading[i],0); 
       } 

       if(execvp(cmd_args[0],cmd_args) == -1) 
       { 
        perror("Problem with command"); 
        exit(0); 
       } 
      } 
      else 
      { 

       wait(&status); 
       close(writing[i]); 

       if(i > 0) 
       { 
        close(reading[i]); 
       } 
      } 
     } 
     else 
     { 
      perror("fork"); 
     } 


     input_file[0] = 0; 
     output_file[0] = 0; 
     run_bg = 0; 
    } 

答えて

2

ループ内の各プロセスを待ってからすべてのファイル記述子を閉じることが問題だと思います。これにより、dup2()への次回の呼び出しでファイル記述子が無効になり、次のプロセスのstdinが変更されません。

私はコードを実行していません。

+0

私はあなたが正しいと思います。私はif(reading [m]!= -1)close(read [m])をコメントアウトしようとしました。私は2つのコマンドをパイプすることができます。正しい方向に私を指してくれてありがとう! – mbxtr

0

I型の「lsを|トイレ」wcが期待通りに行い、lsコマンドでの単語出力の数を出力します。 "|"を使用してコマンドをパイプしているときは、アプリケーションにパイプを作成する必要はありません。最初のコマンドはstdoutに出力する必要があり、2番目のコマンドは標準出力からその出力を読み取る必要があります。

+0

これは配管の仕組みを理解するためのプロジェクトですので、配管をセットアップする必要があります。 "ls | wc"は通常の端末で動作しますが、私はこのプログラムでそれをエミュレートする必要があります。 私が理解するところでは、最初のコマンドの出力を設定する必要があります。この場合は "ls"をパイプの出力に、2番目のコマンドの入力をパイプの入力に設定する必要があります。 – mbxtr

+0

この配管機構を提供するためにシェルを実装する場合は、パイプなどの機構を使用する必要があります。質問者はこれらの問題を知っていると思います。彼はそれがなぜ機能していないのかについて質問しています。 – BobbyShaftoe