1

ソケット接続を受け入れるときに fork() が子プロセスからオフになるサーバーを作成しています。

子がクライアントと通信するとき、その情報の一部を親に送り返す必要があります。これを実現するためにパイプを使用しています。

問題は、親子 IPC を実行しようとすると、子からの入力を読み取るときに親がブロックすることです。つまり、子が同時に実行されていても、それらはすべて親を待っているため、一度に 1 つずつしか処理できません。

私のコードは次のようになります(簡潔にするためにエラーチェックは削除されています):

/* loop: wait for clients to connect */
for(;;) {

  pipe(write_to_parent); /* create pipe between parent and child */
  pipe(write_to_child);  /* create pipe between parent and child */

  newsockfd = accept(...);

  pid = fork();

  if (pid == 0) { /* child process */
      close(write_to_parent[0]);
      close(write_to_child[1]);

     printf("Connected!\n");

     while ((rc = recv(newsockfd, ...)) > 0) {
         /* process socket request */

         /* write stuff to parent that is related to what we recv'd from client */
         rc = write(write_to_parent[1], &buf, 1024);
     }

     printf("Disconnected!\n");

     exit(0);
  } else { /* parent */

      close(write_to_parent[1]);
      close(write_to_child[0]);

       while (read(write_to_parent[0], &buf, 1024) > 0) {
           /* accept data from child process, and do some processing */
       }
  }
}

だから私の質問は、どうすればこれを解決できますか? ブロックされないように、親がパイプを使用して子と通信するにはどうすればよいですか?

これはパイプでも可能ですか、それとも代わりに共有メモリ(セマフォを使用すると思います)またはメッセージキューを使用する必要がありますか? (この投稿を読みました: Unix/Linux IPC の比較ですが、これらのタスクが実際にどのように達成されるかの例を見つけるのは非常に困難です。)

詳細:

次のことを行うテスト プログラムがあります。 1. サーバーに接続する 2. スリープ(5) 3. サーバーから切断する

このプログラムの 2 つのインスタンスを実行すると、サーバーは次のように出力します。

connected!
  // pause for 5 seconds
disconnected!
connected!
  // pause for 5 seconds
disconnected!

明らかに、各クライアントを一度に 1 つずつ処理します。

IPC を削除すると、親と子の両方からパイプ read() と write() を削除すると、次のようになります。

connected!
connected!
  // pause for 5ish seconds
disconnected!
disconnected!

これは私が欲しいものです!

これを達成する方法について何か考えはありますか?(または、この問題を解決しようとしている方法を変更する必要がありますか?)

(編集: これはネットワーク クラスの課題の一部です。集中型サーバーを使用してピアを管理する P2P プロトコルを実装しています。任意の言語を使用できますが、C で試してみようと思いました。)

4

1 に答える 1

2

以下に回答を書きましたが、あなたの質問を読み直したところ、実際の質問を完全に見逃していることに気付きました。ただし、いずれにしても有用な情報になる可能性があります。

同時親の質問に答えるには、親にループを設定して、select()いつでも子からの可能な応答を処理する必要があります。次のことを行う必要があります。

  • 開いている子供の数を追跡する
  • ごとにパイプのセットを保持する
  • ループを使用して、select()着信接続 (いつでも発生する可能性があるため) と、任意の子からの着信データの両方を受け入れます。
  • waitpid()終了した子供を刈り取るために使用する

この手法は強力ですが、適切に設定するには多くの簿記が必要です。


親で開かれたファイル ハンドルは、デフォルトで子プロセスに継承されます。問題は、親と子の両方でパイプの書き込み側がまだ開いているため、親がパイプから読み取るときに、パイプの最後が見えないことです。close(write_to_parent[1])から読み取りを開始する直前に、親でa を使用してみてくださいwrite_to_parent[0]。そう:

} else { /* parent */
     close(write_to_parent[1]);
     while (read(write_to_parent[0], &buf, 1024) > 0) {
         /* accept data from child process, and do some processing */
     }
}
于 2009-02-22T19:50:48.150 に答える