2011-07-08 14 views
3

私はfork()の後に子プロセスでシステムコマンド(またはexecなど)を実行しようとしていて、何らかの入力をプッシュしてから出力を取得しようとしていました。これはfork()の後にあり、pcとcpは親子と親子パイプです。パイプ、フォーク、ノンブロッキングIPC

case 0: 
     /* Child. */ 
     close(STDOUT_FILENO); /* Close current stdout. */ 
     dup2(cp[1], STDOUT_FILENO); 

     close(STDIN_FILENO); 
     dup2(pc[0], STDIN_FILENO); 

     close(pc[1]); 
     close(cp[0]); 
     execlp("cat", "cat", NULL); 
     exit(1); 
    default: 
     /* Parent. */ 
     /* Close what we don't need. */ 
     printf("Input to child:\n"); 

     string theinput("Hey there baby"); 
     write(pc[1], theinput.c_str(), theinput.size()); 
     close(pc[1]); 

     cout << "The input : " << theinput << endl; 


     printf("\nOutput from child:\n"); 
     close(cp[1]); 
     while(read(cp[0], &ch, 1) == 1) 
     { 
      write(1, &ch, 1); 
      outcount++; 
     } 

     exit(0); 

今(あなたがコードしたい場合:http://pastebin.com/Fh7GrxYm)を、うまく動作しているようですが、私はIRCで#posixで話していたとき、彼らはこれが潜在的にブロックすることができる方法について、狂っ、そしてどのようにして"カーネルがどのように感じているかによって異なります"。

同じ事についてのMSDNのブログの記事がありました:http://blogs.msdn.com/b/oldnewthing/archive/2011/07/07/10183884.aspx

はどのようにしてある場合など、ブロッキングを防ぐことができますか?

答えて

1

親プロセスはこのラインに到達したときにあなたのケースでは、デッドロックが発生する可能性がありますが:

​​

「theinputは」多くのデータであれば、親プロセスはpcパイプを埋めることがあります。子プロセス(ここではcat)は、その一部を読むことができますが、すべてではありません。 catあなたに返信します。しかし、もしそれが大量のデータであれば、それはcpパイプをいっぱいにして、誰かがそのパイプからデータを読み込むまでブロックします。これは、親プロセスがpcパイプの排水を待ってブロックされ、cpパイプの内容を消費するコードに到達しないために発生しません。デッドロック。

あなたのIRCの仲間たちによると、このようなことが起こるかどうかは、データの量、パイプがブロックする前に対応できるデータの量(カーネル依存のパラメータ)親や子プロセスによって実行される標準入出力またはその他のバッファリングなどの...

あなたのオプションは以下のとおりです。

  1. 使用外部コマンドを制御するための2つのプロセス:それをデータと読み込み1をフィード1を結果は戻ってくる。このためにはfork()を2回入力する必要があります。これはシェルパイプラインのように見えます。従来、究極のデータソースは孫プロセスであり、フィルタは中位の親であり、究極のデータシンクは、公平プロセスである。

  2. 2つのスレッドを使用して外部コマンドを制御します。前のオプションと同様です。

  3. ノンブロッキングI/Oを使用して外部コマンドを制御します。両方のファイルディスクリプタをfcntl()で非ブロックモードに設定し、いずれかのファイルディスクリプタの準備が完了するのを待つために、poll()またはselect()を使用してイベントループを設定します。いずれかのファイル記述子が準備できたら、write()が部分的にしか完了しないように準備し、read()はすべてを一度に読み込まないように準備します。

  4. glib'sのような既存のイベントループを使用して、それがデータを読み書きする時が来たときに知ってIO Channels、およびwatch themとしてあなたのパイプを設定します。前のオプションと同様ですが、既存のフレームワークを使用するので、既存のアプリケーションイベントループと統合できます。

ところで:あなたのexit(1)_exit(1)が不適切短命子プロセスで終了時のフックを呼び出すことからCライブラリを防ぐためにする必要があります。

関連する問題