回答:
これはあなたの質問に答えると思います:
Richard Stevens(rstevens@noao.edu)から:
基本的な違いは、select()のfd_setはビットマスクであるため、サイズが固定されていることです。カーネルがコンパイルされるときに、カーネルがこのサイズを制限しないことが可能であり、アプリケーションがFD_SETSIZEを必要に応じて定義できるようにします(システムヘッダーのコメントが示すとおり)。4.4BSDのカーネルとSolarisライブラリ関数には、この制限があります。しかし、BSD / OS 2.1はこの制限を回避するようにコード化されているので、プログラミングのほんの少しの問題で、実行可能です。:-)誰かがこれについてSolarisバグレポートを提出し、修正されるかどうかを確認する必要があります。
ただし、poll()を使用する場合、ユーザーはpollfd構造体の配列を割り当て、この配列のエントリ数を渡す必要があるため、基本的な制限はありません。Casperが指摘するように、poll()を持つシステムはselectよりも少ないため、後者の方が移植性が高くなります。また、元の実装(SVR3)では、記述子を-1に設定してカーネルにpollfd構造体のエントリを無視するように指示できなかったため、配列からエントリを削除することが困難でした。SVR4はこれを回避します。個人的には、常にselect()を使用し、ほとんどの場合poll()を使用しています。これは、コードをBSD環境にも移植するためです。これらの環境では、select()を使用するpoll()の実装を誰かが作成する可能性がありますが、私はこれを見たことはありません。select()とpoll()の両方がPOSIX 1003.1gによって標準化されています。
上記のメールは少なくとも2001年のものです。poll()
BSDを含む-コマンドは現在(2017年)すべての近代的なオペレーティングシステムでサポートされています。実際、一部の人々はそれselect()
を廃止すべきだと考えています。意見は別として、周りの移植性の問題poll()
は、現代のシステムではもはや問題ではありません。さらに、epoll()
(manページを読むことができる)以降開発され、人気が高まっています。
最近の開発ではselect()
、明示的に問題はないものの、おそらく使用したくないでしょう。 poll()
、そしてそれはより近代的な進化でありepoll()
、select()
その制限に悩まされることなく同じ機能(およびそれ以上)を提供します。
select
かpoll
:(
このselect()
呼び出しでは、3つのビットマスクを作成して、読み取り、書き込み、およびエラーを監視するソケットとファイル記述子をマークし、オペレーティングシステムは、実際に何らかのアクティビティがあったものにマークを付けます。poll()
ディスクリプタIDのリストを作成し、オペレーティングシステムがそれらのそれぞれに発生したイベントの種類でマークを付けます。
このselect()
方法はかなり不格好で非効率的です。
通常、プロセスで使用できる潜在的なファイル記述子は1,000以上あります。長時間実行するプロセスで開いている記述子が数個しかないが、そのうちの少なくとも1つに高い数が割り当てられている場合、渡されるビットマスクは、select()
その最高の記述子に対応するのに十分な大きさである必要があるため、数百ビットの範囲全体がオペレーティングシステムがselect()
呼び出しが設定されていないことを検出するためだけに、呼び出しごとにループする必要があることを設定解除します。
select()
戻ったら、呼び出し元は3つのビットマスクすべてをループして、発生したイベントを判別する必要があります。非常に多くの一般的なアプリケーションでは、常に1つまたは2つのファイル記述子だけが新しいトラフィックを取得しますが、3つのビットマスクすべてを最後まで読み取って、どの記述子であるかを見つける必要があります。
オペレーティングシステムはビットマスクを書き換えることでアクティビティについて通知するため、ビットマスクは破壊され、リッスンするファイル記述子のリストでマークされなくなります。メモリに保持している他のリストからビットマスク全体を再構築するかmemcpy()
、各select()
呼び出し後に、各ビットマスクとデータブロックの重複コピーを台無しにしたビットマスクの上に保持する必要があります。
したがって、poll()
同じデータ構造を再利用し続けることができるので、アプローチははるかにうまく機能します。
実際、今日のサーバーは一度に何万もの接続を処理することを望んでいるためpoll()
、最近のLinuxカーネルのさらに別のメカニズムに影響を与えていepoll()
ます。これは取り組みの良い紹介です:
http://scotdoyle.com/python-epoll-howto.html
このリンクには、次の利点を示す優れたグラフがありますepoll()
(select()
この時点では、これらのグラフに線が表示されないほど非効率的で古臭いと見なされていることに注意してください!):
http://lse.sourceforge.net/epoll/index.html
更新:スタックオーバーフローの別の質問を次に示します。この質問の回答には、違いの詳細が含まれています。