2017-12-09 7 views
1

私は配管とフォークを使ってCで動作するようにしようとしています: echo "10 + 10のような操作" | bc2つのパイプ、1つのフォーク、bcとexeclp(C)

正確には、私は2つのパイプを作成しようとしました.1つはサーバーが操作を書き、bcが読み込みを行い、もう1つは操作の結果(bc)が行き、サーバーがそれを読み、printfそれ。このために、親プロセスと子プロセスの出力と入力を変更しています。ここで

は私のコードです:

メインint型(){

int t1, t2; 
char resultat[5]; 
int pipe1[2]; 
int pipe2[2]; 

pipe(pipe1); 
pipe(pipe2); 


int resultat_fork = fork(); 

if(resultat_fork == -1){ 
    exit(EXIT_FAILURE); 
} 

if(resultat_fork!=0){ 
    printf("I am the parent\n"); 

    close(pipe1[0]); 
    close(pipe2[1]); 
    //We only want to write into pipe1 and read from pipe2, we can close the two other 

    write(pipe1[1], "20*5\n", 20); 
    //write on pipe1 the expression 

    read(pipe2[0], resultat, sizeof(resultat)); 
    //read from pipe2 the answer (written by bc) 

    printf("resultat : %s\n",resultat); 

    close(pipe1[1]); 
    close(pipe2[0]); 


}else{ 
    printf("I am the children\n"); 

    close(pipe1[1]); 
    close(pipe2[0]); 
    //We only want to write into pipe2 and read from pipe1, we can close the two other 

    dup2(pipe1[0], 0); 
    //redirection standard input to pipe1[0] 

    dup2(pipe2[1], 1); 
    //redirection standard output to pipe2[1] 

    execlp("bc", "bc", NULL); 
    //execute bc, which normaly will read the operation from pipe1 and write the answer into pipe2, but I think it's here the problem come out 

    close(pipe1[0]); 
    close(pipe2[1]); 
} 


return 0; 

}

私は正しい答えを得るが、エラーとしています: 「(standard_in)2 :不正な文字:^ @ " "(standard_in)2:違法文字:: " さらにCTRL Cを押して終了する必要があります。 私はそれがBCから来ると思いますが、なぜ...

私は間違っていますか?ありがとうございました! 私はすでにいくつかの例を見てきましたが、1本のパイプしか投げませんでした。

+0

あなたのテストのために親/子は間違っています。 'fork()'がゼロを返すなら、あなたは子供の中にいる。それ以外の場合、返される値は本質的に値1ではない子のPIDです。 –

+0

「私はここにいる」というメッセージが表示されていれば、両方のプロセスが「私は幼稚な」と言っていますどちらも「私は親である」と言っていません。 –

+0

ありがとうございます。残念だ。私はこれを本当に申し訳なく思っています。今度は私を "(standard_in)1:違法な文字:^ @"と返す。私はそれが正しく使用されていないdup2から来ると信じていますが、私は確信していません – Karl

答えて

1

これは機能します。書き込むデータのサイズと、書き込みと読み取りをどのようにチェックするか、ファイル記述子をどのように閉じるかを指定する方法に注意してください。 (注意:strlen()とは異なりsizeof("string literal")カウントヌル・バイトを、また、コンパイル時の定数ですが、より汎用的なコードは、現在の式の文字列にstrlen()を使用します。。。)親指の

ルール:をあなたにdup2()を使用している場合パイプファイル記述子を標準入力または標準出力に複製する。両方パイプの端を閉じる。

dup()またはfcntl()F_DUPFDまたはF_DUPFD_CLOEXECとして使用する場合も同様です。

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(void) 
{ 
    char resultat[5]; 
    int pipe1[2]; 
    int pipe2[2]; 

    pipe(pipe1); 
    pipe(pipe2); 

    int resultat_fork = fork(); 

    if (resultat_fork == -1) 
    { 
     exit(EXIT_FAILURE); 
    } 

    if (resultat_fork != 0) 
    { 
     printf("I am the parent\n"); 

     close(pipe1[0]); 
     close(pipe2[1]); 

     if (write(pipe1[1], "20*5\n", sizeof("20*5\n") - 1) != sizeof("20*5\n") - 1) 
      fprintf(stderr, "write to child failed\n"); 

     int nbytes = read(pipe2[0], resultat, sizeof(resultat)); 
     if (nbytes <= 0) 
      fprintf(stderr, "read from child failed\n"); 
     else 
      printf("resultat: [%.*s]\n", nbytes, resultat); 

     close(pipe1[1]); 
     close(pipe2[0]); 
    } 
    else 
    { 
     printf("I am the child\n"); 

     close(pipe1[1]); 
     close(pipe2[0]); 
     dup2(pipe1[0], 0); 
     dup2(pipe2[1], 1); 
     close(pipe1[0]); /* More closes! */ 
     close(pipe2[1]); /* More closes! */ 

     execlp("bc", "bc", NULL); 
     fprintf(stderr, "Failed to execute bc\n"); 
     exit(EXIT_FAILURE); 
    } 

    return 0; 
} 

エラー処理を改善する余地がまだあります。エラーの一部を報告した後にコードが実行されますが、これはおそらく最良の動作ではありません。

出力:

I am the parent 
I am the child 
resultat: [100 
] 

(注:。。あなたは、パイプのどこかのプログラムの出力は、あなたがI am the childメッセージが表示されない場合の理由から、なぜ、printf() anomaly after fork()を参照してください)

+0

ありがとうございます。私はすぐにコードをテストすることはできませんが、できるだけ早くそれを試して回答します。 – Karl

関連する問題