selectがfdリストをたどる必要があるという多くの比較を見てきましたが、これは遅いです。しかし、なぜepollはこれを行う必要がないのでしょうか?
2 に答える
これについては多くの誤った情報がありますが、本当の理由は次のとおりです。
典型的なサーバーは、たとえば 200 の接続を処理する場合があります。データの書き込みまたは読み取りが必要なすべての接続にサービスを提供し、さらに作業が必要になるまで待機する必要があります。待機中に、これら 200 の接続のいずれかでデータを受信した場合は中断する必要があります。
ではselect
、カーネルは、接続ごとに 1 つずつ、200 の待機リストにプロセスを追加する必要があります。これを行うには、プロセスを待機リストに追加するための「サンク」が必要です。プロセスが最終的に起動したら、200 個の待機リストすべてからプロセスを削除し、それらのサンクをすべて解放する必要があります。
対照的に、epoll
では、epoll
ソケット自体に待機リストがあります。プロセスは、1 つのサンクのみを使用して、その 1 つの待機リストにのみ配置する必要があります。プロセスが起動したら、1 つの待機リストから削除する必要があり、1 つのサンクだけを解放する必要があります。
明確にするために、epoll
では、epoll
ソケット自体をこれらの 200 接続のそれぞれに接続する必要があります。ただし、これは、接続が最初に受け入れられたときに、接続ごとに 1 回行われます。そして、これは、接続が削除されるときに、接続ごとに 1 回破棄されます。対照的に、select
そのブロックへの各呼び出しは、監視されているすべてのソケットのすべての待機キューにプロセスを追加する必要があります。
皮肉なことにselect
、最大のコストは、アクティビティのないソケットにアクティビティがあったかどうかを確認することです。では、アクティビティがあった場合、そのアクティビティが発生したときにソケットにepoll
通知されているため、アクティビティのないソケットをチェックする必要はありません。epoll
ある意味では、select
呼び出すたびに各ソケットをポーリングして、ソケットのアクティビティ自体がプロセスに通知するようにリギングしselect
ながらアクティビティがあるかどうかを確認します。epoll
との主な違いは、epoll
待機するファイル記述子のリストには 1 回の呼び出しの間だけ存在し、呼び出し元のタスクは 1 回の呼び出しの間だけソケットの待機キューに留まるということです。一方、 では、待機したい他の複数のファイル記述子からのイベントを集約する単一のファイル記述子を作成するため、監視対象の fd のリストは長く続き、タスクは複数のシステム コールにわたってソケット待機キューに留まります。 . さらに、fd は複数のタスク間で共有できるため、待機キュー上の単一のタスクではなく、それ自体が別の待機キューを含む構造であり、現在待機しているすべてのプロセスを含みます。select
select()
select()
epoll
epoll
epoll
fd。void*
(実装に関しては、これは、関数ポインタとその関数に渡すデータ ポインタを保持するソケットの待機キューによって抽象化されます)。
そのため、メカニズムをもう少し説明すると、次のようになります。
epoll
ファイル記述子には、struct eventpoll
この fd に接続されている fd を追跡するプライベートがあります。また、現在この fdで実行struct eventpoll
中のすべてのプロセスを追跡する待機キューもあります。また、現在読み取りまたは書き込みに使用できるすべてのファイル記述子のリストもあります。epoll_wait
struct epoll
epoll
を使用して fd にファイル記述子をepoll_ctl()
追加epoll
するstruct eventpoll
と、その fd の待機キューに が追加されます。また、fd が現在処理の準備ができているかどうかもチェックし、そうであれば、準備完了リストに追加します。epoll
を使用して fd を待機するepoll_wait
と、カーネルは最初に準備完了リストをチェックし、ファイル記述子の準備が整っている場合はすぐに戻ります。そうでない場合は、 内の単一の待機キューに自身を追加し、struct eventpoll
スリープ状態になります。epoll()
ed中のソケットでイベントが発生すると、epoll
コールバックが呼び出され、ファイル記述子が準備完了リストに追加され、現在そのソケットで待機しているすべてのウェイターも起動しますstruct eventpoll
。
struct eventpoll
当然のことながら、さまざまなリストや待機キューに対して慎重にロックする必要がありますが、それは実装の詳細です。
注意すべき重要なことは、上記のどの時点でも、対象のすべてのファイル記述子をループするステップについて説明していないことです。完全にイベントベースであり、長時間続く fd のセットと準備完了リストを使用することにより、epoll は操作に O(n) 時間かかることを回避できます。ここで、n は監視されているファイル記述子の数です。