epoll相关的系统调用
epoll相关的系统调用:
- epoll_create: 用来创建一个epoll文件描述符
- epoll_ctl: 用来添加/修改/删除需要侦听的文件描述符及其事件
- epoll_wait:接收发生在被侦听的描述符上的,用户感兴趣的IO事件
- epoll_pwait: 可屏蔽指定信号的epoll_wait
要尽量少调用epoll_ctl,防止其带来的开销抵消其带来的好处,添加/修改/删除被侦听文件描述符都需要调用epoll_ctl,所以,有的时候应用中可能存在大量的短连接(比如web服务器),epoll_ctl将被频繁的调用,可能成为系统的瓶颈
-
打开一个epoll监听文件描述符,之后给这个epoll_fd注册要监听的连接描述符,epfd其实就是一个监听的池,之后要把要监听的连接丢到池子里,就可以监听这些连接描述符发生了什么。
/************************ 返回一个epoll文件描述符,size表示epoll能监听的最大连接数 从linux2.6.8开始,size参数被忽略,必须大于零 在最初中,是提示内核,给其分配多大的内存,当然,在初始中,如果超过了,内核也将分配更多的空间 现在,这个提示不再需要,内核会动态的分配空间,根据需要调整数据结构的大小 但是大小必须大于0,以便于在较旧的内核上运行时,向后兼容。 *************************/ int epoll_create(int size); // 总之,这个函数返回一个epoll文件描述符,用于随后所有的epoll调用
-
注册连接描述符 此处,epoll_event.events没有完全搞清楚,待之后补充
/********************* epoll注册函数,select是在监听事件时告诉内核要监听什么类型的事件,这里是先注册要监听的事件类型 epfd:epoll_create(int size)函数的返回值, op: 表示动作,添加删除修改 EPOLL_CTL_ADD:注册新的fd到epfd中; EPOLL_CTL_MOD:修改已经注册的fd的监听事件; EPOLL_CTL_DEL:从epfd中删除一个fd; fd: 要监听的连接描述符,注册fd到epfd这个池子中 typedef union epoll_data { void *ptr; int fd; __uint32_t u32; __uint64_t u64; } epoll_data_t; struct epoll_event { __uint32_t events; // Epoll events 要监听的事件类型 epoll_data_t data; // User data variable 在这里,我们使用联合体中的fd,表示要监听连接描述符 }; events描述要监听的事件类型,可以是以下的组合 EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭); EPOLLOUT:表示对应的文件描述符可以写; EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来); EPOLLERR:表示对应的文件描述符发生错误; EPOLLHUP:表示对应的文件描述符被挂断; EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。 * EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里 *********************/ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
-
注册完后,需要知道哪些描述符是可操作的,用epoll_wait等待一组描述符(也即前面注册的)上的事件
/********************* epfd: 等待的监听描述符,也就是哪个池子中的内容 *events: 指针,指向epoll_event的数组,监听描述符中的连接描述符就绪后,将会依次将信息填入 maxevents: 最多返回最大事件 timeout: 等待时间,要是有连接描述符就绪,立马返回,如果没有,timeout时间后也返回,单位是ms epoll_wait()将会一直阻塞直到:epfd产生事件 / 被信号处理函数打断 / 超时。 *********************/ int epoll_wait(int epfd,struct epoll_event * events, int maxevents,int timeout);
-
直接用close即可关闭连接,同时epoll也不会再监听
int close(int fd); // 关闭连接