1 #include <sys/epoll.h>
2 int epoll_create(int size);//创建一个epfd,标识内核中的事件表
3 int epoll_ctl(int epfd, int op,int fd, struct epoll_event *event);//向epfd中添加,删除,修改事件
4 int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);//从epfd中取出实际发生的事件
epoll使用一组函数来完成任务,将用户感兴趣的fd上的事件放在内核里的一个事件表中,epoll使用一个额外的fd来唯一标识内核中的这个事件表。
创建一个epoll对象epfd。
int epoll_create(int size);
size:给内核一个提示,告诉内核事件表需要多大;事件表中会维护一棵红黑树和一个双向链表,将监听的fd集合放到红黑树中,将实际发生事件的fd集合放到双向链表中。
返回值:返回一个fd,标识内核事件表;
对epoll对象进行操作,将需要监听的事件和对应的fd加到内核事件表中的红黑树。
int epoll_ctl(int epfd, int op,int fd, struct epoll_event *event);
epfd:标识内核事件表的fd;
op:指定操作类型,用三个宏来表示
EPOLL_CTL_ADD-向epfd中注册fd上的事件;EPOLL_CTR_MOD-在epofd中修改fd上注册的事件;EPOLL_CTL_DEL-从epfd中删除fd上注册的事件;
fd:需要操作(监听)的fd;
event:epoll_event结构指针类型(含需要监听的事件类型和对应的fd),告诉内核需要监听事件类型和对应的fd。
1 struct epoll_event
2 {
3 _uint32_t events; //epoll监听的的事件类型(注册的事件),一系列事件的按位或
4 epoll_data_t data; //联合体,存储用户数据,使用最多的是fd
5 };
6
7 typedef union epoll_data
8 {
9 void* ptr;
10 int fd; //事件所从从属的fd,使用最多
11 uint32_t u32;
12 uint64_t u64;
13 }epoll_data_t; //联合体,同一时刻只能保存一个成员的值
epoll的事件类型:
EPOLLIN-数据可读;EPOLLRDNORM-普通数据可读;EPOLLRDBAND-优先级带数据可读;EPOLLPRI-高优先级数据可读;
EPOLLOUT-数据可写;EPOLLWRNORM-普通数据可写;EPOLLWRBAND-优先级带数据可写;
EPOLLRDHUP-TCP连接对方关闭或者对方关闭了写操作;
EPOLLERR-错误;EPOLLHUP-挂起;EPOLLNVAL-fd没有打开;
EPOLLET-将epoll设为边缘触发(ET)模式,另一种模式为水平触发(LT)模式;
EPOLLONESHOT-只监听一次事件,监听结束后,如果要继续监听事件对应的fd,需要将这个fd再次加入到epoll队列中。
返回值:调用成功,返回0;调用失败,返回-1。
监听(注册)的事件中实际发生的事件,epoll_wait函数如果检测到就绪事件,就将就绪事件从epfd标识的内核事件表中的双向链表中复制到events指向的数据结构中(仅含检测到的就绪事件)。
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); epfd:标识内核事件表的fd;
events:epoll_event结构类型的链表(链表的的数据域为结构体),实际发生的事件;
maxevents:监听fd的数量;
timeout:设置epoll的超时时间,单位为毫秒;
返回值:timeout=0,epoll_wait调用立即返回,非阻塞;timeout=-1,epoll_wait调用阻塞,直到某个事件发生。
调用成功,返回就绪的fd的数量;调用失败,返回-1并设置errno。
LT模式和ET模式
采用LT模式的fd,当应用程序调用epoll_wait检测到fd上有事件发生,将发生的事件通知应用程序,应用程序可以不立刻处理该事件,当应用程序下次调用epoll_wait时,epoll_wait会继续将发生的事件通知应用程序,知道该事件被处理;
采用LT模式的fd,当应用程序调用epoll_wait检测到fd上有事件发生,将发生的事件通知应用程序,应用程序必须立刻处理该事件,当应用程序再次调用epoll_wait是,将不再将发生的事件通知应用程序。
相比LT模式,ET模式减少了事件被重复触发的次数,效率较高。