什么是epoll
多路复用io接口select/poll的增强版本,显著提高程序在大量并发连接中只有少量活跃情况下的cpu利用率
epoll的优缺点
优点
1. 支持大数目的FD
2. IO效率不随FD数量增加而线性下降
3. 使用mmap加速用户空间和内核空间的消息数据传递
缺点
1. 活动连接比较多的时候,频繁调用epoll_await性能会下降明显
epoll的使用
主要函数定义
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
完整例子
/*
参考:https://linux.die.net/man/4/epoll
*/
#define MAX_EVENTS 10
struct epoll_event ev, events[MAX_EVENTS];
int listen_sock, conn_sock, nfds, epollfd;
/* Set up listening socket, 'listen_sock' (socket(),
bind(), listen()) */
epollfd = epoll_create(10);
if (epollfd == -1) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
perror("epoll_ctl: listen_sock");
exit(EXIT_FAILURE);
}
for (;;) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_sock) {
conn_sock = accept(listen_sock,
(struct sockaddr *) &local, &addrlen);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
epoll的原理
精巧的是使用3个api(epoll_create,epoll_ctl,epoll_wait),epoll_ctl这个设置fd事件的不需要频繁调用,epoll_wait需要频繁调用,但是没有传入参数,而且epoll_wait不会受fd的数量增多影响。
epoll的扩展
与select、poll的比较
比select支持更多的描述符,描述符多了性能下降不会那么厉害
epoll的惊群效应
主进程创建好listen_fd、epollfd后,由各个子进程或线程调用epoll_wait等待监听套接字内容,当有连接进来时候,
会有部分进程被唤醒,但是实际只有一个进程会被accept成功,其他的会返回EAGAIN错误码
解决方法:Nginx中使用mutex全局互斥锁,每个子进程在epoll_wait()之前先去申请锁,申请到则继续处理,获取不到则等待
支持的最大FD数目
它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max查看,一般来说这个数目和系统内存关系很大。
参考链接
https://www.cnblogs.com/lojunren/p/3856290.html
https://www.cnblogs.com/fnlingnzb-learner/p/5835573.html
https://www.jianshu.com/p/397449cadc9a
https://linux.die.net/man/4/epoll