web-dev-qa-db-ja.com

pollとselectの違いは何ですか?

POSIX標準 select および poll システムC APIコールを参照しています。

153
Sasha

this はあなたの質問に答えると思います:

リチャード・スティーブンス([email protected])から:

基本的な違いは、select()のfd_setはビットマスクであるため、サイズが固定されていることです。カーネルのコンパイル時にカーネルがこのサイズを制限しないようにすることで、アプリケーションがFD_SETSIZEを(今日のシステムヘッダーのコメントが示唆するように)何でも定義できるようになりますが、より多くの作業が必要になります。 4.4BSDのカーネルとSolarisライブラリ関数の両方にこの制限があります。しかし、BSD/OS 2.1はこの制限を回避するようにコーディングされているため、わずかなプログラミングで実行可能です。 :-)誰かがこれについてSolarisバグレポートを提出し、それが修正されるかどうか確かめるべきです。

ただし、poll()を使用する場合、ユーザーはpollfd構造体の配列を割り当て、この配列のエントリ数を渡す必要があるため、基本的な制限はありません。 Casperが指摘しているように、selectよりも少ないシステムがpoll()を持っているため、後者はより移植性があります。また、元の実装(SVR3)では、記述子を-1に設定して、pollfd構造内のエントリを無視するようカーネルに指示することができなかったため、配列からエントリを削除することが難しくなりました。 SVR4はこれを回避します。個人的には、コードをBSD環境にも移植するため、私は常にselect()とめったにpoll()を使用しません。これらの環境では、誰かがselect()を使用するpoll()の実装を作成できますが、私は見たことがありません。 select()とpoll()の両方がPOSIX 1003.1gで標準化されています。

2017年10月の更新:

上記の電子メールは少なくとも2001年と同じです。 poll()コマンドは現在(2017年)、BSDを含むすべての最新のオペレーティングシステムでサポートされています。実際、一部の人々はselect()非推奨 と信じています。意見はさておき、poll()の周りの移植性の問題は、現在のシステムではもはや問題ではありません。さらに、epoll()はその後開発され( manページを読む )、人気が高まり続けています。

近代的な開発では、おそらくselect()を使用したくないでしょうが、明示的に問題はありません。 poll()、およびより現代的な進化epoll()は、select()と同じ機能(およびそれ以上)を提供し、その制限に悩まされることはありません。

81
akappa

select()呼び出しでは、3つのビットマスクを作成して、読み取り、書き込み、エラーを監視するソケットとファイル記述子をマークし、オペレーティングシステムは実際に何らかのアクティビティがあったものをマークします。 poll()は記述子IDのリストを作成し、オペレーティングシステムはそれらのそれぞれに発生したイベントのkindをマークします。

select()メソッドはかなり不格好で非効率的です。

  1. 通常、プロセスで使用可能なファイル記述子は1000を超える可能性があります。長時間実行されるプロセスで開いている記述子がわずかで、少なくとも1つに高い番号が割り当てられている場合、select()に渡されるビットマスクは、その最高の記述子に対応するのに十分な大きさでなければなりません。設定されていないことを検出するために、select()呼び出しごとにオペレーティングシステムがループする必要があるという設定が解除されます。

  2. select()が返されると、呼び出し元は3つのビットマスクすべてをループして、発生したイベントを判別する必要があります。非常に多くの典型的なアプリケーションでは、常に1つまたは2つのファイル記述子のみが新しいトラフィックを取得しますが、3つのビットマスクすべてを最後まで読み取って、それらの記述子を発見する必要があります。

  3. オペレーティングシステムはビットマスクを書き換えることでアクティビティについて通知するため、ビットマスクは台無しになり、リッスンしたいファイル記述子のリストでマークされなくなります。メモリに保持する他のリストからビットマスク全体を再構築するか、各memcpy()呼び出し後に各ビットマスクとselect()の複製コピーを台無しにされたビットマスクの上に保持する必要があります。

したがって、poll()アプローチは、同じデータ構造を再利用し続けることができるため、はるかにうまく機能します。

実際、poll()は、現代のLinuxカーネルのさらに別のメカニズムに影響を与えています。今日のサーバーは一度に数万の接続を処理することが多いため、スケーラビリティをさらに向上させるメカニズムをさらに改善するepoll()です。これは、取り組みの優れた紹介です。

http://scotdoyle.com/python-epoll-howto.html

このリンクにはepoll()の利点を示すいくつかの素敵なグラフがあります(select()はこの時点では非効率的で旧式であるため、これらのグラフに線が入らないことに注意してください!):

http://lse.sourceforge.net/epoll/index.html


更新:以下に、スタックオーバーフローに関する別の質問を示します。その答えは、相違点についてさらに詳しく説明しています。

Twistedでのselect/pollとepollリアクターの警告

219
Brandon Rhodes