epoll 使用詳解--epoll_wait


關鍵API:

epoll_wait, epoll_pwait, epoll_pwait2 等待epoll中的I/O事件發生。

概要:

#include <sys/epoll.h>

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t *sigmask);
int epoll_pwait2(int epfd, struct epoll_event *events, int maxevents, const struct timespec *timeout, const sigset_t *sigmask);

參數描述:

  epfd :epoll文件描述符
  events :接口的返回參數,一般都是一個數組,數組長度大於等於maxevents。
  maxevents:期望捕獲的事件的個數。
  timeout :超時時間(>=0),單位是毫秒ms,-1表示阻塞,0表示不阻塞。

  sigmask:需要屏蔽信號的掩碼,可以避免wait時被信號打斷。

 

函數返回值:

  ret: 函數返回值
    正常捕獲事件后返回事件的個數。
    超時返回0.

  只有在下面的情況下才會返回:
    1、有至少一個事件發生。
    2、調用過程中被信號中斷?
    3、超時。

  events:函數輸出參數
    這個和create時是同一個數據結構,events就是很多事件的集合,data就是create時設置的值(原樣返回)。

    struct epoll_event {
        uint32_t events; /* Epoll events */
        epoll_data_t data; /* User data variable */
      };

拓展API:

  epoll_pwait()
    epoll_wait()與epoll_pwait()的區別類似,select(2)與pselect(2)。epoll_pwait()可以讓程序安全的等到事件的發生,一般的epoll_wait()處理線程,在阻塞期間是可能被信號中斷的。
    當線程處理完信號函數以后,再次返回時,epoll_wait()不會繼續阻塞,而是推出,返回-1。
  調用方法:
    ready = epoll_pwait(epfd, &events, maxevents, timeout, &sigmask);
  實現:
    函數的內部可以理解為原子的調用了下面的這些函數:

    pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
    ready = epoll_wait(epfd, &events, maxevents, timeout);
    pthread_sigmask(SIG_SETMASK, &origmask, NULL);

  參數:
    sigmask: 希望阻塞的信號列表,如果為NULL,這個api和epoll_wait()功能一模一樣。

  epoll_pwait2()
    和epoll_pwait()區別就是增加了超時時間。
  調用:

    int epoll_pwait2(int epfd, struct epoll_event *events, int maxevents, const struct timespec *timeout, const sigset_t *sigmask);

  參數:
    timeout:可以指定納秒級別的時間。

返回值:   

成功返回I/O事件的個數,超時返回0。失敗返回-1,會設置錯誤碼error。

錯誤碼:   

  EBADF :apfd不是一個有效的描述符
  EFAULT :參數events指向的內存區域不可寫。
  EINTR :阻塞過程中被信號中斷,epoll_pwait()可以避免,或者錯誤處理中,解析error后重新調用epoll_wait()。

  EINVAL :epfd不是一個epoll文件描述符,或者參數maxevents小於等於0。

注釋:   

  1、當某個線程阻塞在epoll_wait(),另外一個線程可以往這個epfd中添加新的套接字。而且如果這個套接字事件發生,也會被阻塞的線程捕獲事件。
  2、如果epoll中已經有超過maxevents 個事件,當前成功返回后,再次調用,獲取的事件將從上次取得結尾地方開始獲取。可以理解為內部是一個隊列,先進先出,事件再次
  觸發只能往后面插入,epoll_wait()從頭取,避免出現餓死的情況。
  3、如果epoll_wait()一個空的epfd,將會導致永遠阻塞。如果epoll_wait()過程中,epfd監視列表被其它線程清空了也一樣。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM