【IO复用之epoll】
epoll是Linux特有的IO复用函数。它使用一组函数完成IO复用,而select和poll使用一个函数。
epoll不需要像select和poll那样每次调用都要重复传入文件描述符和事件集。但epoll在内核会使用一个额外的文件描述符,来标识内核中事件表。
epoll原理
epoll在内核维护一个事件表(用一个额外的描述符表示,红黑树),和一个就绪事件队列。在有事件表中的事件就绪时,epoll将就绪事件放入就绪队列,并通过回调通知用户态。
select和poll需要轮询所有的事件表,时间复杂度为O(n)。epoll通过回调,只需要遍历就绪队列,时间复杂度为O(1)
epoll函数签名
#include <sys/epoll.h>
int epoll_create(int size);
int epoll_ctl(int epfd, int op, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
struct epoll_event
{
__uint32_t events; /* epoll事件 */
epoll_data_t data; /* 用户数据 */
};
typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
- epoll_create会返回一个事件表的文件描述符,后续epoll_ctl、epoll_wait都操作该描述符。size参数现在不起作用,仅仅时告诉内核,事件表需要多大。
- epfd即epoll_create返回的事件表。epoll_event中的events记录了等待的事件类型,data用来记录用户数据。
编程模板
int ret = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
for (int i = 0; i < ret; i++)
{
int sockfd = events[i].data.fd;
/* do something */
}

浙公网安备 33010602011771号