エポール
EpollはLinuxの効率的なネットワークの基盤です。たとえば、イベントポーリング(nodejsなど)はlibevを使用し、libevの最下層はepollです(ただし、プラットフォームによってはepollまたはkqueueを使用する場合があります)。
epollは、何百万ものハンドル監視を効率的にサポートできます。
Epollは、赤黒木レコードによって追加されたソケットを使用し、二重にリンクされたリストを使用してカーネルによってトリガーされたイベントを受信するため、効率的です。システムレベルでサポート:
プロセスがepoll_createメソッドを呼び出すと、Linuxカーネルはeventpoll構造体を作成します。この構造体には、epollの使用方法に密接に関連する2つのメンバーがあります。
eventpollの構造は次のとおりです。
struct eventpoll{
....
/*红黑树的根节点,这颗树中存储着所有添加到epoll中的需要监控的事件*/
struct rb_root rbr;
/*双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件*/
struct list_head rdlist;
....
};
この記事を参照してください:http://blog.csdn.net/u010657219/article/details/44061629
各epollオブジェクトには、epoll_ctlメソッドを介してepollオブジェクトに追加されたイベントを格納するための独立したeventpoll構造があります。
これらのイベントはすべて赤黒木にマウントされるため、繰り返されるイベントを赤黒木で効率的に識別できます(赤黒木の挿入時間効率はlgnで、nは木の高さです)。
また、epollに追加されたすべてのイベントは、デバイス(ネットワークカード)ドライバーとのコールバック関係を確立します。つまり、このコールバックメソッドは、対応するイベントが発生したときに呼び出されます。このコールバックメソッドは、カーネルではep_poll_callbackと呼ばれ、発生するイベントをrdlistの二重リンクリストに追加します。
epollでは、イベントごとに、以下に示すようにエピテム構造が作成されます。
struct epitem{
struct rb_node rbn;//红黑树节点
struct list_head rdllink;//双向链表节点
struct epoll_filefd ffd; //事件句柄信息
struct eventpoll *ep; //指向其所属的eventpoll对象
struct epoll_event event; //期待发生的事件类型
}
下の図の左上隅のテキストは間違っています。二重にリンクされたリストの各ノードは、エピテム構造のrdllinkメンバーに基づいているはずです。
上記の文のより具体的な説明は次のとおりです(なぜ何百万ものハンドルをサポートできるのか):
1. 配達を繰り返す必要はありません。epoll_waitを呼び出すときは、過去にselect / pollを呼び出すことと同じですが、カーネルはepoll_ctlで監視するハンドルのリストをすでに取得しているため、現時点では、ソケットハンドルをカーネルに渡す必要はありません。 。
2.カーネルでは、すべてがファイルです。したがって、epollはファイルシステムをカーネルに登録して、上記の監視対象ソケットを格納します。epoll_createを呼び出すと、この仮想epollファイルシステムにファイルノードが作成されます。もちろん、このファイルは通常のファイルではなく、epollのみを提供します。
epollがカーネルによって初期化されると(オペレーティングシステムが起動されると)、epoll独自のカーネル高速キャッシュ領域が開かれ、監視する各ソケットが配置されます。これらのソケットは、カーネルキャッシュに次の形式で保存されます。赤黒木。高速検索をサポートするには、挿入と削除を行います。このカーネル高速キャッシュ領域は、連続した物理メモリページを作成し、その上にスラブレイヤーを構築するためのものです。簡単に言えば、必要なサイズのメモリオブジェクトを物理的に割り当て、毎回アイドルメモリを使用することです。割り当てられたオブジェクト。
3.非常に効率的な理由:
これは、epoll_createを呼び出すと、カーネルがepollファイルシステムでファイルノードを構築するのに役立つだけでなく、カーネルキャッシュに赤黒木を構築して、将来epoll_ctlからソケットを格納するだけでなく、それを構築するためです。リストリンクリストは、準備完了イベントを格納するために使用されます。epoll_waitが呼び出されたら、このリストリンクリストにデータがあるかどうかを確認してください。データがある場合は戻り、データがない場合はスリープし、タイムアウト後にリンクリストにデータがない場合でも戻ります。したがって、epoll_waitは非常に効率的です。
この準備完了リストのリストはどのように維持されますか?epoll_ctlを実行すると、epollファイルシステムのファイルオブジェクトに対応する赤黒木にソケットを配置することに加えて、カーネル割り込みハンドラーのコールバック関数を登録して、カーネルに割り込みが到着すると、準備完了リストに配置されます。したがって、ソケットにデータがある場合、カーネルはネットワークカード上のデータをカーネルにコピーした後、ソケットを準備完了リストに挿入します。(注:この文をよく理解してください!)
上記の文からわかるように、epollの基本はコールバックです!
このように、赤黒木、準備ができたハンドルのリンクリスト、および少量のカーネルキャッシュは、大規模な同時実行下でのソケット処理の問題を解決するのに役立ちます。epoll_createを実行すると、赤黒木と準備完了リンクリストが作成されます。epoll_ctlを実行すると、ソケットハンドルが追加されている場合は、赤黒木に存在するかどうかを確認します。存在する場合は、すぐに戻ります。存在しない場合は、トランクに追加してから、コールバック関数をカーネルに登録します。割り込みイベントが発生したときに、準備完了リンクリストにデータを挿入するために使用されます。epoll_waitを実行すると、レディリストのデータをすぐに返すことができます。
最後に、epollの2つの固有のモード、LTとETを見てください。LTモデルとETモデルの両方が上記のプロセスに適用できます。違いは、LTモードでは、ハンドルのイベントが一度に処理されない限り、将来epoll_waitが呼び出されたときにハンドルが何度も返されるのに対し、ETモードは初めて戻るだけであるということです。 。
LTとETについては、説明があります。LTとETはどちらも電子機器の用語です。ETはエッジトリガー、LTは水平トリガーです。1つは変化のマージンでのみトリガーされることを意味し、もう1つは変化のマージンでのみトリガーされることを意味します。特定の段階でトリガーされます。
この記事を参照してください:https://zhuanlan.zhihu.com/p/20315482
LTとETの実際のコード実験については、ここを参照してください:http://www.cnblogs.com/charlesblc/p/5521086.html
ETとEPOLL_ONESHOTについては、こちらをご覧ください:http://www.cnblogs.com/charlesblc/p/5538363.html
epoll統合イベントのソースコードについては、http://www.cnblogs.com/charlesblc/p/5554785.htmlを参照してください。
LT、ETはどのようにそれを行いましたか?ソケットハンドルにイベントが発生すると、カーネルはハンドルを上記のレディリストリンクリストに挿入します。このとき、epoll_waitを呼び出してレディソケットをユーザーモードメモリにコピーし、リンクされたレディリストをクリアします。リスト、そして最後にepoll_waitが行うことは、これらのソケットがETモード(つまり、LTモードのハンドル)でない場合、これらのソケットをチェックすることです。これらのソケットに未処理のイベントがある場合、ハンドルを準備完了に戻します。空になったばかりのリスト。したがって、ET以外のハンドルの場合、イベントがある限り、epoll_waitは毎回このハンドルを返します。(上記の段落から、LTにはまだ再生プロセスがあり、非効率的であることがわかります)
より詳細な内容については、次の2つの記事を読むことができます。
http://blog.csdn.net/russell_tao/article/details/7160071
http://www.open-open.com/lib/view/open1410403215664.html