谈谈对Epoll的理解

目录

一、背景

二、Epoll的基本介绍

三、Epoll在Select上做了哪些改进

四、讲讲Epoll的原理


一、背景

上周写了对Linux下的Select机制的理解,这周带着Select的基础谈谈对Epoll的理解,讲讲Epoll在Select的基础上到底做了什么样的优化从而更加深入的理解网络IO中的IO多路复用机制。

二、Epoll的基本介绍

Linux内核为处理大批量文件描述符在Select基础上进行了优化就成了Epoll。

Epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

三、Epoll在Select上做了哪些改进

1、使用了eventpoll新的结构体,改进了Select在fd_set有1024位的限制,能够支持监听更多的文件描述符,系统能最大可以打开文件的数目,一般来说这个数目受限于系统内存,1GB内存的机器上大约是10万左右,具体数目可以使用 cat /proc/sys/fs/file-max进行查看。

2、对于Socket文件描述符的监听(增删改查)底层使用了红黑树的结构,查询的复杂度在O(logN)。

3、减少了fd由用户态拷贝内核态、内核态拷贝用户态的过程。同时也不用每次调用需要重置调用参数。

4、调用返回结果只返回就绪列表,减少了无用的遍历次数。(select机制会把fd_set所有位置都遍历一遍找到有事件发生的fd)

上面做的优化其实就是本质上就是为了能够支持更多的客户端连接,以及客户端多了以后,性能并不会随着客户端的增多而直线下降。

四、讲讲Epoll的原理

(1)Epoll跟Select相比,拆分了三个方法

epoll_create()

创建epoll句柄(可以理解为你写程序创建一个全局对象,后续所有的操作都要基于这个全局对象来进行逻辑处理)

epoll_ctl() 

将你想要监听的文件描述符,加入到监听的集和里面(底层使用红黑树进行维护)

epoll_wait()

真正的调用方法,会返回就绪列表,然后就可以针对就绪列表读取具体的事件。

从一个开发人员的角度,epoll其实也是非常符合面向对象的思想,我觉得可以总结为:

初始化-维护数据-操作数据 。非常像我们写面向对象代码的习惯。

接下来结合自己的理解,画了一个图去理解Epoll机制

谈谈对Epoll的理解_第1张图片

 

五、总结

Epoll在Select的基础上确实解决了几大痛点问题。

(1)客户端数量限制

(2)大量的文件描述符拷贝

(3)Select随着监听的文件描述符增加遍历效率低下问题。

从整体来看,Epoll还是比Select有更多的优势以及更好的性能体现。毕竟也是在Select的基础上进行优化,如果想看看Epoll的真实的运用场景,个人建议可以看看Redis的实现,是基于 IO多路复用(Epoll) + Reactor模式进行实现,加深对Epoll的理解。

你可能感兴趣的:(linux,服务器,c语言,网络)