2016-12-11 14 views
4

私は、ループwhile-trueの中でwaitpid()read()を待つことを試みています。具体的には、これらの2つのイベントのいずれかを待っていて、ループの各反復で処理します。現在、私は以下の実装をしています(これは私が望むものではありません)。ループ内の2種類のイベントを待つ方法(C)?

while (true) { 
    pid_t pid = waitpid(...); 
    process_waitpid_event(...); 

    ssize_t sz = read(socket, ....); 
    process_read_event(...); 
} 

この実装の問題は、2番目のイベントの処理が最初のイベントの完了に依存することです。この2つのイベントを順次処理する代わりに、ループの各繰り返しで最初に起こるイベントを処理したいと考えています。私はこれをどのようにするべきですか?

+0

あなたは非同期の方法でそれをしたいですか? –

+1

これはスレッド問題のようなものです。 Cでスレッディングを実装する方法を検索することができます。 –

+0

問題を詳しく説明してください。あなたのためのwaitpidは何ですか、あなたは何から読んでいますか?特に、子プロセスを1つしか持たず、出力を読み込みたいが、終了時を知る必要があるのはなぜですか? –

答えて

3

あなたがスレッドに触れることをしたくない場合は、あなたがwaitpidへの呼び出しのオプションでこれを含めることができます。waitpidのマンページからも

pid_t pid = waitpid(pid, &status, WNOHANG); 

WNOHANG - リターン子供が出ていない場合はすぐに

このように、waitpidが準備ができていないと、ブロックされず、プログラムは次の行に進みます。

readについては、ブロックしている場合はpoll(2)をご覧ください。設定した間隔ごとにソケットが準備されているかどうかを確認することができます。使用している場合はreadに電話してください。これによりブロックされません。

あなたのコードは少し次のようになります。これは、ちょうどあなたのコード内の変数名から判断すると、あなたがソケットからINGのreadだと仮定している

// Creating the struct for file descriptors to be polled. 
struct pollfd poll_list[1]; 
poll_list[0].fd = socket_fd; 
poll_list[0].events = POLLIN|POLLPRI; 
// POLLIN There is data to be read 
// POLLPRI There is urgent data to be read 

/* poll_res > 0: Something ready to be read on the target fd/socket. 
** poll_res == 0: Nothing ready to be read on the target fd/socket. 
** poll_res < 0: An error occurred. */ 
poll_res = poll(poll_list, 1, POLL_INTERVAL); 

。他の人が言っているように、あなたの問題はスレッディングのようなもう少し重い義務を必要とするかもしれません。

+0

SIGCHLDを扱うのではなく、なぜこのようなことを示唆しているのですか? –

+0

ユーザはもともと信号を処理しないwaitpidを使用していたので、もちろん、プログラムが子プロセスを待っているという条件で有効なオプションです。 –

+0

cmon。 SIGCHLDのハンドラをインストールし、EINTRを読み込みから処理することは、ほとんどの場合に適切な方法です。提案された解決法は、ループにもっと多くのシステムコールを追加し、何もしなくてもスレッドを起動させるという点で劣っています。しかし、もっと重要なことに、OPが最初にループ内でwaitpidを行う理由があるかどうかは非常に不明です。彼らは単に子供を産んだだけで、出産後は読書をやめたいと思っています。解決策は何も残らなくなるまで読書を続け、後にwaitpidで終了ステータスを収集することです。 –

1

@DanielPorteousの答えは、あなたのプログラムでスレッドを使いたくない場合にも有効です。

考え方は簡単です。waitpidreadの機能は、操作に時間がかかります。考え方は、waitpidが操作全体に影響を与えるものがない場合は、すぐに戻り、同じことが読み取り操作にもなるように、タイムアウトメカニズムを維持しています。

read関数がバッファ全体の読み取りに非常に時間がかかる場合は、read関数から読み取りを手動で制限することができます。そのため、全体を一度に読み取るのではなく、2ミリ秒読み込みます。実行するwaitpid関数へのサイクル。

しかし、その目的のためにスレッドを使用して安全に実装するのはかなり簡単です。 Here's a nice guidelineスレッドの実装方法について

あなたの場合、2つのスレッドを宣言する必要があります。

pthread_t readThread; 
pthread_t waitpidThread; 

これで、スレッドを作成し、特定の関数をパラメーターとして渡す必要があります。

pthread_create(&(waitpidThread), NULL, &waitpidFunc, NULL); 
pthread_create(&(readThread), NULL, &readFunc, NULL); 

今すぐあなたのwaitpidFuncreadFunc機能を記述する必要があります。彼らはこのように見えるかもしれません。

void* waitpidFunc(void *arg) 
{ 
    while(true) { 
     pid_t pid = waitpid(...); 

     // This is to put an exit condition somewhere. 
     // So that you can finish the thread 
     int exit = process_waitpid_event(...); 

     if(exit == 0) break; 
    } 

    return NULL; 
} 
0

私はこのような状況で適切なツールがselectまたはpollだと思います。どちらも本質的に同じ仕事をしています。入力が可能な記述子を選択することができます。したがって、例えば2つのソケットで同時に待つことができます。しかし、あなたがプロセスとソケットを待っていたいので、あなたのケースでは直接使用することはできません。解決策は、waitpidの終了時に何かを受け取るパイプを作成することです。

新しいスレッドを起動して、パイプで元のスレッドと接続することができます。新しいスレッドはwaitpidを呼び出し、終了するとその結果をパイプに書き込みます。メインスレッドは、selectを使用してソケットまたはパイプのいずれかを待機します。

+0

私の無知を許して、これをSIGCHLDの使用と対照できますか?あなたが提示しているものは、はるかに関与しているように見え、私が見るどんな利益ももたらさない。また、OPが最初に何かを必要とするかどうかは不明ですが、実際にパイプを持っていて、それを閉じるのを待つ必要があることは間違いありません。 –

関連する問題