私はselectがfdリストを調べなければならないという多くの比較を見てきましたが、これは遅いです。しかし、なぜこれを行う必要はありませんか?
これについて多くの誤った情報がありますが、本当の理由はこれです:
典型的なサーバーは、たとえば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
とselect
の主な違いは、select()
では、待機するファイル記述子のリストが単一のselect()
の期間だけ存在することです。呼び出し、および呼び出しタスクは、単一の呼び出しの間、ソケットの待機キューにのみ留まります。一方、epoll
では、待機する他の複数のファイル記述子からイベントを集約する単一のファイル記述子を作成します。そのため、監視対象のfdのリストは長続きし、タスクはソケットにとどまります。複数のシステムコールにわたる待機キュー。さらに、epoll
fdは複数のタスク間で共有できるため、待機キュー上の単一のタスクではなく、epoll
fd。 (実装の観点から、これは、関数ポインターとその関数に渡す_void*
_データポインターを保持するソケットの待機キューによって抽象化されます)。
それで、メカニズムをもう少し説明するために:
epoll
ファイル記述子には、このfdにどのfdがアタッチされているかを追跡するプライベート_struct eventpoll
_があります。 _struct eventpoll
_には、このfdで現在_epoll_wait
_ ingであるすべてのプロセスを追跡する待機キューもあります。 _struct epoll
_には、現在読み取りまたは書き込みに使用できるすべてのファイル記述子のリストもあります。epoll_ctl()
を使用してepoll
fdにファイル記述子を追加すると、epoll
はそのfdの待機キューに_struct eventpoll
_を追加します。また、fdが現在処理の準備ができているかどうかを確認し、準備ができている場合は、準備完了リストに追加します。epoll_wait
_を使用してepoll
fdで待機すると、カーネルは最初に準備リストをチェックし、ファイル記述子が既に準備されている場合はすぐに戻ります。そうでない場合、それは_struct eventpoll
_内の単一の待機キューに自分自身を追加し、スリープ状態に入ります。epoll()
edされているソケットでイベントが発生すると、epoll
コールバックが呼び出されます。これにより、ファイル記述子がレディリストに追加され、現在待機中のウェイターも起動されますその_struct eventpoll
_。明らかに、_struct eventpoll
_およびさまざまなリストと待機キューには多くの注意深いロックが必要ですが、それは実装の詳細です。
重要なことは、上記のどの時点でも、対象のすべてのファイル記述子をループするステップを説明しなかったことです。完全にイベントベースであり、fdの長続きするセットとレディリストを使用することにより、epollはO(n)の取得を回避できます操作の時間(nはファイル記述子の数)監視されています。