nettyのepollとlinuxのepollはどのように実装されていますか

1.Linux epoll

Epollは、Linuxカーネルの拡張可能なIOイベント処理メカニズムであり、Linux 2.5.44カーネルで最初に導入されました。これは、POSIXの選択およびポーリングシステム呼び出しの代わりに使用でき、アプリケーション要求が多数ある場合に改善できます。パフォーマンス(この時点で監視されているファイル記述子の数は非常に多く、操作を完了するために古いselectおよびpollシステム呼び出しで必要なO(n)とは異なります。EpollはO(1)時間で操作を完了することができるため、パフォーマンスは非常に高くなります)、 Epollは、操作のために独自のファイル記述子をユーザースペースに提供するという点でFreeBSDのkqueueに似ています。

1.効率的なepoll

Epollは、Linuxでの効率的な多重化テクノロジーであり、Linuxでの高性能ネットワークサーバーの重要なテクノロジーでもあります。ネットワークソケットリンクを介してリモートリソースをローカルメモリにロードします。このパフォーマンスを最適化する方法は?

二、epollは理由を提案します

2.1。ポーリングと選択は、以前のAIOと比較して大幅に改善されていますが、「待機キュー」と「ブロックプロセス」を監視する必要があるため、パフォーマンスはまだ完全には解放されていません。このとき、CPUは他のプロセスに奪われ、コンテキストスイッチングのパフォーマンスが消費されます。

2.2。そのソケットからのデータを認識するために、selectをトラバースする必要があるため、selectは、各socketChanelをウェイクアップするために1つずつトラバースすることしかできません。

3、epollの原則

3.1 epollは複数のソケットを監視し、待機キューを維持するための選択を改善し、プロセスをブロックしてさらに改善します。これらの2つのステップを分離します。

3.2epoll_ctlメンテナンス待機キュー

3.3epoll_waitブロッキングキュー

4、eventpoll

4.1 epoll_createメソッドを呼び出すと、eventpollオブジェクトも作成されます。

4.2 eventpollは準備完了リストを維持します。ソケットからのデータがある場合、そのソケットは準備完了リストに追加されます。

4.3ブロッキングプロセスは、レディリストのコールバックを受信し、ソケットデータ送信を開始できます。

2.nettyのepoll

Nettyを使用してサーバーを構築する場合は、親スレッドプールと子スレッドプールを指定する必要があります。親スレッドはポートのリッスンを担当します。接続が接続されると、子スレッドプールのスレッドに登録されます。接続のIO操作/タスクはこれによって制御されます。スレッドが完了しました。つまり、1つのスレッドが複数の接続されたIO操作、つまり多重化を担当します。Nettyの最下層は、システムが提供するselectまたはepollを使用して多重化を実現します。

まず、人気のある科学の下で選択/ポーリング/エポールに来てください。

選択/ポーリング

サーバーは各接続を確立します。これは、ファイルを開くのと同じで、対応するファイル記述子(fd)を取得します。同じ送信元IP /送信元ポート/宛先IP /宛先ポートは同じfdに対応します。

selectとpollは似ていますが、selectは配列を使用して接続制限がありますが、pollはリンクリストを使用して接続制限がありません。

接続を監視する場合、ユーザー層の観点から、(1)読み取り/書き込み/異常イベントに焦点を合わせ、タイムアウト期間を設定し、システムが提供するselectメソッドを呼び出す3つのfdアレイが構築されます。(2)selectメソッドを呼び出すときは、fd配列をカーネル状態に転送し、fdの一部が準備できるのを待ってから、fd配列(準備完了状態を含む)をユーザー状態に戻す必要があります。(3)ユーザープログラムはfd配列をトラバースし、準備完了fdを処理します。 (4)selectメソッドを呼び出します。

欠点は、(1)fd配列が渡され、fd配列全体が返されるたびに発生するため、ユーザー空間とカーネル空間に多数の相互コピーが発生することがわかります。(2)ユーザープログラムは、準備ができているfdを見つけるために、fd配列をトラバースする必要があります。

システム層の観点から、 selectメソッド(1)を呼び出すときは、fd配列をトラバースし、fdごとに、対応するpollメソッド(対応するデバイスドライバーによって実装される)を呼び出し、fdが配置されているスレッドを待機キューに追加し、準備ができているかどうかを確認します。ステータス、関心のある準備完了ステータスを記録します。(2)関心のある準備完了状態がある場合は、直接戻ります。(3)関心のある準備完了状態がない場合は、スリープ状態になり、fdの準備ができるのを待ってから、待機キュー内のスレッドをウェイクアップします。(4)ウェイクアップした後、1-を繰り返します。 4つの操作。

欠点は、すべてのfdを毎回チェックする必要があることです。

epoll

epollはselectに比べて大幅に改善されています。(1)epollを使用する場合、epollオブジェクトが最初に作成されます。(2)接続アクセスがあると、epollオブジェクトに挿入されます。epollオブジェクトは、実際には赤黒ツリー+二重リンクリストです。fdは赤黒ツリーに挿入され、赤黒ツリーを使用して、繰り返されるかどうかが確認されます。(3)一度fd準備完了。コールバックをトリガーしてfdを準備完了リストに挿入し、待機キュー内のスレッドをウェイクアップします。(4)epoll_waitメソッドを呼び出すときは、準備完了リンクリストがある場合はそれを確認するだけでよく、待機キューに入っていない場合はユーザープログラムに戻ります。

epollはfdを管理するため、毎回繰り返す必要がなく、準備ができたfdを返すだけなので、ユーザースペースとカーネルスペースの相互コピーが減り、fdの数が多いほど効率的です。

Nettyは、さまざまな多重化手法を使用することを選択できます。

NioEventLoop

NioEventLoopの最下層は、システムに応じてselectまたはepollを選択します。Windowsシステムの場合、最下層はWindowsSelectorProvider(select)を使用して多重化を実現します。Linuxの場合は、epollを使用します。

選択モードの場合、newKeys、updateKeys、およびcancelledKeysは、新しく追加されたfdであるNioEventLoopに対応するセレクターで維持され、fdの関心状態を更新し、fd監視をキャンセルします。接続が接続または切断されるたびに、NioEventLoopの登録/登録解除メソッドが呼び出され、これらのコレクションが更新されます。(これがJDK11の実装であり、PollArrayWrapperはJDK8で直接更新されます)

NioEventLoopの実行中は、登録された接続を継続的に監視します。コアロジックはdoSelectメソッドにあります。主な操作は、(1)processUpdateQueueで、newKeys、updateKeys、cancelledKeysのキーをPollArrayWrapper(2)subSelectorに更新します。 poll()は、実際にはネイティブメソッドを呼び出しており、PollArrayWrapperのfdをreadFds / writeFds / exceptionFdsにコピーし、これらのfdを監視します。

プライベートネイティブint型poll0(長いpollAddress、int型numfds、
             INT [] readFds、INT [] writeFds、INT [] exceptFds、長いタイムアウト)。

(3)updateSelectedKeys、freadFds / writeFds / exceptionFdsをトラバースし、readyfdをselectedKeyに保存します

fdの準備ができると、doSelectメソッドが返され、アプリケーションはselectedKeyをトラバースして処理できます。

EpollEventLoop

EpollEventLoopの最下層は、epollを使用して多重化を実装します。

EpollEventLoopは、epollFd、eventFd、およびtimerFdを初期化します。

  • epollFdは、systemメソッドを呼び出すことによって生成されるepollオブジェクトであり、将来監視する必要があるすべてのfdを管理するために使用されます。

  • eventFdはスレッド通信に使用されます。プログラムはeventFdをepollFdに追加し、eventFdを監視します。eventFdが操作を行うと、epoll_waitを呼び出すスレッドをウェイクアップします。

  • TimerFdはタイミングに使用されます。同じモニターtimerFdは、時間に達すると、epoll_waitを呼び出すスレッドが起動されます。

接続が接続または切断されるたびに、epoll_ctl_add / epoll_ctl_delメソッドが呼び出されてepollオブジェクトが操作されます。

EpollEventLoopのrunメソッドでは、すべてのfdを監視するためにepoll_waitが呼び出されます。fdの準備ができると、EpollEventArrayにコピーされ、アプリケーションはEpollEventArrayをトラバースしてすべての準備ができたイベントを処理します。

おすすめ

転載: blog.csdn.net/madongyu1259892936/article/details/109496167