浅析epoll

什么是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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值