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