2017-09-24 4 views
0

このフォーラムではパイプの読み書きに関する多くの質問がありますが、私は問題を解決できません。以下 コードスニペットは、以下のことを行います。コマンドライン引数のファイル名を通じ親プロセスがパイプ内の子プロセスによって書き込まれたデータを読み取ることができない

  1. がpipe_pて子プロセスに渡される
  2. 子プロセスが指定されたファイルを開き、に親プロセスのためにpipe_cために、その内容を書き込みます画面に表示されます。

すべてがうまくいきますが、親プロセスは(何も印刷していないので)パイプからデータを読み取ることができません。 子プロセスでデータを正常に書き込むことができました。なぜなら、親プロセスではなく子プロセスブロックでパイプを通じてコン​​テンツを印刷できるからです。

注:STEP 4は

誰もが私にこれを助けてください動作しません。

コード:

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

int main(int argc, char **argv){ 

    int pipe_p[2], pipe_c[2]; 
    int childpid, c, k = 0; 
    char buffer[1000] = {0}; 
    FILE *file; 

    pipe(pipe_p); 
    pipe(pipe_c); 

    childpid = fork(); 

    if(childpid){ 
     //parent process block 
     //STEP 1 ------- 
     close(pipe_p[0]); //closing reading side of pipe 
     write(pipe_p[1], argv[1], strlen(argv[1])); 
     close(pipe_p[1]); 
     //-------------- 
     wait(NULL); 
     //-------------- 
     //printf("%s\n", "Its working"); 
     //STEP 4 ------- 
     close(pipe_c[1]); 
     read(pipe_c[0], buffer, sizeof(buffer)); 
     close(pipe_c[0]); 
     printf("%s\n", buffer); 
     //-------------- 
    } 
    else{ 
     //child process block 
     //sleep(1); 
     //STEP 2 ------- 
     close(pipe_p[1]); 
     read(pipe_p[0], buffer, sizeof(buffer)); 
     close(pipe_p[0]); 
     //printf("%s\n", buffer); 
     //-------------- 

     //STEP 3 ------- 
     file = fopen(buffer, "r"); 
     while((c = getc(file)) != EOF){ 
      buffer[k++] = c; 
     } 
     buffer[k] = 0; 
     //printf("%s", buffer); 
     close(pipe_c[0]); 
     write(pipe_c[1], buffer, strlen(buffer)); 
     close(pipe_c[1]); 
     //-------------- 
    } 

    return 0; 
} 

答えて

1

私はこのコードで5個のバグを参照してください。私はそれらを最も重要なものから最も重要なものへとリストアップするつもりです。私はバグを修正しようとはしていないので、これらのバグの裏に隠されているものがもっとあるかもしれません。

  • sys/wait.hを含むのを忘れました。コンパイラは、waitの暗黙の宣言について不平を言っていたはずです。コンパイラが苦情をしなかった場合は、すべての警告をオンにしてください。

  • システムコールが失敗しているかどうかはチェックしていません。 すべてのシステムコールの後に、失敗のチェックを続ける必要があります。障害が発生した場合は、stderrに、失敗したシステムコールの名前、関連するすべてのファイルの名前(存在する場合)、およびstrerror(errno)を含む障害の完全な説明を出力し、終了しないで終了するコード。あなたがこれをしていれば、実際には、特定のものがではなく、 "うまくいきました"ということをあなた自身が発見したでしょう。

  • 詳細には、子が正常に終了しなかったかどうかをチェックしていません。 wait(NULL)の代わりに、親はwaitpid(childpid, &status, 0)を実行していて、終了ステータスをデコードし、にメッセージを出力してWIFEXITED(status) && WEXITSTATUS(status) == 0以外のものを出力し、正常に終了していないはずです。

  • 親では、間違った場所にwaitが呼び出されています。 pipe_cのすべてのデータを読み込んで処理した後、waitに電話する必要があります。それ以外の場合、子プロセスがパイプバッファを完全に埋めると、プログラムはデッドロックします。 (また、のすべてののパイプからの最初の1000バイトだけでなく、読み取る必要があります。)

  • この子では、バッファオーバーランが発生しています。ファイルから無制限の量のデータをbufferに読み込んでいますが、bufferは固定サイズです。必要に応じてmallocreallocを使用して拡大するか、bufferより大きいサイズのチャンクでファイルからパイプにコピーする必要があります。

Iは、大きなファイルからの入力と、(それがフォークの両側をトレース)-fモードでは、straceユーティリティでプログラムを実行することによって、これらの問題のすべてを発見しました。これは貴重なデバッグ手法であり、自分で試してみるべきです。

+0

ur提案のおかげで@zwol。私は4番目の点を持っていませんでした。ここでは、親プロセスが子プロセスがバッファを埋めるまで待機しています(これは正常に実行され、他の部分のprintf部分のコメントを外して確認できます)。しかし、親コンテキストに戻った後、子プロセスで読み込まれるデータは読み込まれません。 –

+0

よろしくお願いします。あなたがコードを動作させることができれば素晴らしいだろう。ありがとうございました –

+0

@ChanchalRoshan子プロセスでバッファオーバーランを修正し、_large_テストファイル(少なくとも32KB)を使用すると、待ち時間が早すぎるというデッドロックが発生するはずです。現在、デッドロックはバッファオーバーランによってマスクされているため、パイプバッファをいっぱいにする前に子がクラッシュします。 – zwol

関連する問題