1

私のアプリケーションには、recv() と send() に使用する Unix TCP ソケットが 1 つしかありません。ソケットはノンブロッキングです。これを考えると、send()/recv() の前に select() を実行する利点はありますか?

基礎となる TCP パイプが I/O の準備ができていない場合、send()/recv() は EWOULDBLOCK または EAGAIN ですぐに戻る必要があります。では、select() を実行する意味は何ですか? この場合、追加のシステムコールのオーバーヘッドが発生するだけのようです。何か不足していますか?

編集:言及するのを忘れました:アプリケーションはシングルスレッドです。

4

3 に答える 3

2

ソケットが非ブロッキングである場合、(ソケットが非ブロッキングでない場合) 発生するブロッキングの代わりにブロックする必要がありますselect(または、制限pollの破れと関連する危険がないことが望ましい)。FD_SETSIZEsendrecv。そうしないと、何もしないために 100% の CPU 時間を使用してスピンします。selectほとんどの場合、ソケットをブロックして/をなくすのと同じくらい簡単ですpoll。ただし、考慮すべき興味深いケースが 1 つあります。プログラムがブロックされ、ソケットの反対側のプログラムもブロックされている場合 (またはその逆)、 IO をブロックするとデッドロックになる可能性があります。ノンブロッキング IO および/sendsendselectpoll、出力を書き込むことができない場合、この状況を自然に検出し、保留中の入力を処理します。

于 2013-05-23T18:50:18.550 に答える
1

ループ内で recv() を実行することもできますが、そうすると大量の CPU 時間を消費することになります。

余分な CPU オーバーヘッドを避けるために、select() を待機することをお勧めします。バックグラウンド タスクを実行する必要がある場合は、select() にタイムアウトを追加して、ネットワーク トラフィックがなくても定期的に起動できるようにします。

于 2013-05-23T17:19:52.320 に答える
0

アプリケーションがレイテンシーに敏感な場合は、select() を使用せずにタイトな recv() ループでスピンし、専用の CPU を割り当てることが正当化される場合があります (そうしないと、スケジューラーがそれを罰し、膨大なレイテンシーが発生することになります)。アプリに余裕がないが、このソケットにサービスを提供するスレッドがある場合は、読み取り側でソケット ブロックを作成し、データが利用可能になったときにスケジューラがスレッドを起動できるようにします。送信側では、必要なものに応じて、ソケットをブロックするかスピンします。

アプリケーションがシングル スレッドで、ロジックが "receive-process-reply" である場合にのみ、非ブロッキングの読み取り/書き込みソケット、セレクター、および書き込みキューが絶対に必要です。書き込み可能に登録し、書き込み可能になったらキューをソケットにフラッシュし、書き込み可能から登録解除します。可読性は常に登録する必要があります。

于 2013-05-23T19:27:09.570 に答える