8

私はイベントベースのプログラミングにかなり慣れていません。私は、読み取り/書き込みの準備が整ったファイルのみを通知するように見えるepoll's edge-modeを試しています (既に準備ができているか準備ができているかに関係なく、すべての準備ができているファイルを通知する level-mode とは対照的です)。

よくわからないのは、エッジモードでは、私がepoll_waiting していないときに発生する準備イベントが通知されるかどうかです。まだリアームされていないワンショット ファイルのイベントはどうなりますか?

なぜそれを求めているのかを説明するために、次のシナリオを考えてみましょう。

  • 10 個のノンブロッキング ソケットが接続されている
  • edge-mode + oneshotepoll_ctlで、ソケットの読み取り準備が整ったときに反応するように構成します。EPOLLET | EPOLLONESHOT | EPOLLIN
  • epoll_wait何かが起こる (最大 10 件のイベントを報告)
  • Linux がプロセスを起動し、ソケット #1 と #2 の準備ができていることを報告します
  • Ireadとプロセス データ ソケット #1 (までE_AGAIN)
  • Ireadとプロセス データ ソケット #2 (までE_AGAIN)
  • 私がそれをしている間、ソケットSはデータを受け取ります
  • すべてのイベントを処理したので、トリガーされたファイルをepoll_ctlinEPOLL_CTL_MODモードでリアームします。
  • epoll_wait私のループは次のイベントのバッチに戻ります

わかりました、それで、ソケットSの準備ができていることを最後にepoll_wait 常に通知しますか? Sが #1 の場合のイベント(つまり、再装備されていない) ?

4

1 に答える 1

8

私は epoll の edge-mode を試しています。これは明らかに読み取り/書き込みの準備が整ったファイルのみを通知します (既に準備ができているか準備ができているかに関係なく、すべての準備ができているファイルを通知する level-mode とは対照的です)。

まず、システムを明確に把握しましょう。システムがどのように機能するかについての正確なメンタル モデルが必要です。あなたの見解epoll(7)はあまり正確ではありません。

エッジ トリガーとレベル トリガーの違いは、イベントを正確に作成するものの定義です。前者は、ファイル記述子でサブスクライブされたアクションごとに 1 つのイベントを生成します。イベントを消費すると、そのイベントを生成したすべてのデータを消費しなくても、イベントはなくなります。OTOH、後者は、イベントを生成したすべてのデータを消費するまで、同じイベントを何度も生成し続けます。

これらの概念を実行に移す例を次に示しますman 7 epoll

  1. パイプ (rfd) の読み取り側を表すファイル記述子は、epoll インスタンスに登録されます。

  2. パイプライターは、パイプの書き込み側に 2 kB のデータを書き込みます。

  3. epoll_wait(2) への呼び出しが行われ、rfd が準備完了のファイル記述子として返されます。

  4. パイプ リーダーは、rfd から 1 kB のデータを読み取ります。

  5. epoll_wait(2) への呼び出しが行われます。

EPOLLET (エッジ トリガー) フラグを使用して rfd ファイル記述子が epoll インターフェースに追加されている場合、ステップ 5 で行われた epoll_wait(2) への呼び出しは、ファイル入力バッファーに利用可能なデータがまだ存在するにもかかわらず、ハングする可能性があります。一方、リモート ピアは、すでに送信したデータに基づいた応答を期待している可能性があります。これは、監視対象のファイル記述子で変更が発生した場合にのみ、エッジ トリガー モードがイベントを配信するためです。したがって、ステップ 5 で、呼び出し元は、入力バッファー内に既に存在するデータを待機することになる可能性があります。上記の例では、2 で行われた書き込みのために rfd のイベントが生成され、イベントは 3 で消費されます。4 で行われた読み取り操作はバッファ データ全体を消費しないため、epoll_wait(2) の呼び出しが行われます。手順 5 では、無期限にブロックされる可能性があります。

つまり、根本的な違いは「イベント」の定義にあります。エッジ トリガーでは、イベントを 1 回消費する単一のユニットとして扱います。level-triggered は、イベントの消費が、そのイベントに属するすべてのデータの消費と同等であると定義します。

さて、それで、具体的な質問に取り組みましょう。

エッジモードでは、epoll_waiting を行っていないときに発生する準備イベントが通知されますか?

はい、そうです。内部的には、カーネルは各ファイル記述子で発生した興味深いイベントをキューに入れます。これらは への次の呼び出しで返されるためepoll_wait(2)、イベントが失われることはありません。まあ、保留中の他のイベントがあり、渡されたイベント バッファがepoll_wait(2)それらすべてに対応できない場合、次の呼び出しでは正確ではないかもしれませんが、要点は、最終的にこれらのイベントが報告されるということです。

まだリアームされていないワンショット ファイルのイベントはどうなりますか?

繰り返しますが、イベントを失うことはありません。ファイル記述子がまだ再準備されていない場合、興味深いイベントが発生した場合、ファイル記述子が再準備されるまで、単にメモリ内のキューに入れられます。リアームされる、保留中のイベント (ディスクリプタがリアームされる前に発生したイベントを含む) は、次の呼び出しで報告されますepoll_wait(2)(正確には次の呼び出しではないかもしれませんが、報告されます)。つまり、EPOLLONESHOTイベント監視を無効にするのではなく、単にイベント通知を一時的に無効にします。

では、最後の epoll_wait は常にソケット S の準備ができていることを通知されるのでしょうか? S が #1 の場合 (つまり、再装備されていない場合) はどうなりますか?

上で述べたことを考えると、今ではかなり明確になっているはずです。はい、そうなります。イベントを失うことはありません。epoll は強力な保証を提供します。また、スレッドセーフであり、異なるスレッドで同じ epoll fd を待機し、イベント サブスクリプションを同時に更新できます。epoll は非常に強力で、時間をかけて学習する価値があります。

于 2015-07-24T22:08:06.763 に答える