select, poll, epoll

4753 ワード

select, poll, epoll
IO多重化で広く使われているselect、poll、epollモデルでは、IO多重化の実現の主旨は、アプリケーション自身がクライアント接続を監視するのではなく、代わりにカーネルがアプリケーションの代わりにファイルを監視することである.
select
/* @Param:
   nfds:                          1,                        
   readfds:             ,      
   writefds:                ,      
   exceptfds:                ,         ,      
   timeout:         ,3   : 
                   1. NULL(     ); 
                   2.   timeval,      ; 
                   3.   timeval     0,          ,  */
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • selectモデルを使用してIO要求と同期ブロックモデルを処理するのは大きな違いはありません.監視socketを追加したり、select関数を呼び出す追加操作を追加したりして、効率はもっと悪いですが、selectモデルは1つのスレッド内で複数のsocketのIO要求を同時に処理することができます.つまり、処理された接続数があまり高くなければ、selectを使用するウェブサーバは、multi-threading+blocking IOを使用するウェブサーバよりも必ずしも性能が良いとは限らず、遅延が大きい可能性があります.selectの利点は、単一の接続に対してより速く処理できるのではなく、より多くの接続
  • を処理できることです.
  • selectを呼び出すたびにfd_setセットは、fd_set集合が大きい場合、このオーバーヘッドも大きい
  • selectはポーリングモデルを採用しており、selectを呼び出すたびにカーネルに渡されるすべてのfd_を巡回する必要がある.set,fd_set集合が大きい場合、このオーバーヘッドも大きい
  • データコピーを減らすためにfd_をポーリングするsetによるパフォーマンスの破損、カーネル対監視fd_setコレクションサイズが制限されており、これはマクロFD_を介してSETSIZE制御は、一般的に32ビットプラットフォームが1024、64ビットプラットフォームが2048であり、プロセスが開くファイル記述子の個数を単純に変更してもselect傍受ファイルの個数
  • を変更することはできない.
    poll
    /*  
        @Param
        struct pollfd {
            int fd;           ///      
            short events;     ///      
            short revents;    ///               
        };
    */
    int poll(struct pollfd *fds, nfds_t nfds, int timeout);

    1つのpollfd構造体は、監視されたファイル記述子を表し、fds[]を渡すことによってpoll()が複数のファイル記述子を監視することを示す.ここで、構造体のeventsドメインは、ファイル記述子を監視するイベントマスクであり、ユーザがこのドメインを設定し、構造体のreventsドメインはファイル記述子の操作結果イベントマスクであり、カーネルは呼び出しが返されたときにこのドメインを設定する.eventsドメインで要求されたイベントは、reventsドメインで返される可能性があります.
    合法的な事件は以下の通りです.
    POLLINデータ読み取り可能
    POLLRDNORMには通常のデータ読み取り可能
    POLLRDBANDは、優先データ読み取り可能である
    POLLPRIは緊急データ読み取り可能
    POLLOUT書き込みデータはブロックされません
    POLLWRNORM書き込み通常データは、POLLWRBAND書き込み優先データをブロックすることはありません.POLLMSGSIGPOLLメッセージをブロックすることはありません.
    複数のイベントをリスニングする必要がある場合は、
    POLLIN|POLLRDNORMはeventsドメインを設定します.poll呼び出し後にイベントが発生したかどうかを検出すると、
    fds[i].revents&POLLINで判断します.
  • pollは本質的にselectと区別されないが、最大接続数の制限はない.なぜなら、チェーンテーブルに基づいて格納されているため、ユーザが入力した監視が必要なファイル記述子をカーネル空間にコピーし、各fdに対応するデバイスの状態をクエリーし、デバイスが準備できたらデバイス待機キューに1つを追加し、遍歴を継続するためである.すべてのfdを巡回した後に準備デバイスが発見されなかった場合、現在のプロセスは、デバイスが準備完了またはアクティブタイムアウトするまで保留され、起動後に再びfd
  • を巡回する.
  • pollはselect監視ファイル記述子の数の制限のみを解決し、呼び出すたびにファイル記述子をプログラム空間(ユーザ空間)からカーネル空間にコピーし、カーネルの下部にあるすべてのファイル記述子をポーリングする必要があるパフォーマンスオーバーヘッド
  • を変更しません.
    epoll
    /*     epoll  ,  size                 ,        */
    int epoll_create(int size);
    
    /*     epoll            :  、  、   */
    /*  @Param
        epfd:   epoll_creat   
        op:     , 3     :
                EPOLL_CTL_ADD (    fd epfd),
                EPOLL_CTL_MOD (       fd     ),
                EPOLL_CTL_DEL ( epfd    fd);
        event:             
                struct epoll_event {
                    __uint32_t events; // Epoll events 
                    epoll_data_t data; // User data variable 
                };
                typedef union epoll_data {
                    void *ptr;
                    int fd;
                    uint32_t u32;
                    uint64_t u64;
                } epoll_data_t;
    */
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
    
    /*                   */
    /*  @Param
        epfd:       epoll_creat   
        events:             
        maxevents:        events   ,  maxevents        epoll_create()  size
        timeout:         
                    -1:   
                     0:     ,   
                    >0:     
           :                      ,      0,    -1
    */
    int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
  • epollはLinuxのIO多重select/pollの拡張バージョンであり、開発者がイベントを待つたびにリスニングされるファイル記述子の集合を再準備する必要がなく、プログラムが大量の同時接続でわずかにアクティブな場合のシステムCPU利用率を著しく向上させることができる.もう1つの理由は、イベントを取得する際に、リスニングされた記述子セット全体を巡回する必要がなく、カーネルIOイベントによって非同期に起動されてReadyキューに追加された記述子セットを巡回すればよい(ポーリングではなくコールバックメカニズムを採用し、FD数の増加に伴って効率が低下せず、アクティブで利用可能なFDのみがcallback関数を呼び出す)
  • 表面はepollが非常に良好に見えるが、接続数が少なく、接続が非常に活発な場合、selectとpollの性能はepollよりも優れている可能性がある.epollは大量の関数コールバックの基礎の上に構築されているため、
  • である.
  • epollはselect/pollのようなIOイベントの水平トリガ(Level Triggered、水平トリガはデータがあればトリガする)を提供するほか、エッジトリガ(Edge Triggered、エッジトリガはデータが来てこそトリガし、キャッシュ領域にデータがあるかどうかにかかわらず)を提供し、ユーザー空間プログラムがIO状態をキャッシュする可能性があり、epoll_を減少させる.wait/epoll_pwaitの呼び出し、アプリケーション効率の向上
  • インスタンスの使用
    https://blog.csdn.net/lisongl...
    参考記事
    https://zhuanlan.zhihu.com/p/...