上网一搜epoll,基本是这样的结果出来:《多路转接I/O – epoll模型》,万变不离这个标题。
但是呢,不变的事物,我们就更应该抓出其中的重点了。
多路、转接、I/O、模型。
别急,先记住这几个词,我比较喜欢你们看我文章的时候带着问题。
有的朋友可能对select也不是很了解啊,我这里稍微科普一下:网络连接,服务器也是通过文件描述符来管理这些连接上来的客户端,既然是供连接的服务器,那就免不了要接收来自客户端的消息。那么多台客户端,消息那么的多,要是漏了一条两条重要消息,那也不要用TCP了,那怎么办?
前辈们就是有办法,轮询,轮询每个客户端文件描述符,查看他们是否带着消息,如果带着,那就处理一下;如果没带着,那就一边等着去。这就是select,轮询,颇有点领导下基层的那种感觉哈。
但是这个select的轮询呐,会有个问题,明眼人一下就能想到,那即是耗费资源啊,耗费什么资源,时间呐,慢呐(其实也挺快了,不过相对epoll来说就是慢)。
再认真想一下,还浪费什么资源,系统资源。有的客户端呐,占着那啥玩意儿不干那啥事儿,这种客户端呐,还不少。这也怪不得人家,哪儿有客户端时时刻刻在发消息,要是有,那就要小心是不是恶意攻击了。那把这么一堆偶尔动一下的客户端的文件描述符一直攥手里,累不累?能一次攥多少个?就像一个老板,一直想着下去巡视,那他可以去当车间组长了哈哈哈。
所以,select的默认上限一般是1024(FD_SETSIZE),当然我们可以手动去改,但是人家给个1024自然有人家的道理,改太大的话系统在这一块的负载就大了。
那句话怎么说的来着,你每次对系统的索取,其实都早已明码标价!哈哈哈。。。
所以,我们选用epoll模型。
讲到这里啊,如果对 select 不了解的朋友可以打开百度搜一下了,因为我们接下来要讲的内容需要你对 select 有点了解的。
以前从没想过select和poll,一出来关注的就是epoll,后来明白了,对于select,也是有很多细节在里面的。源码之前,了无秘密!!!
#define FD_SETSIZE 1024
#define NFDBITS (8 * sizeof(unsigned long))
#define __FDSET_LONGS (FD_SETSIZE/NFDBITS)
typedef struct {
unsigned long fds_bits[__FDSET_LONGS];
} fd_set;
为什么源码要写成1024?
我觉得是历史遗留原因吧,不信你看一下你服务器在不改动的情况下能允许的最大文件描述符数。
如果有人再问:那 select 就只能监听1024个?那我就要说道说道了,谁说有1024?select 性能就这样了,再往上开意义不大,真要开,编源码去嘛。
epoll接口是为解决Linux内核处理大量文件描述符而提出的方案。该接口属于Linux下多路I/O复用接口中select/poll的增强。其经常应用于Linux下高并发服务型程序,特别是在大量并发连接中只有少部分连接处于活跃下的情况 (通常是这种情况),在该情况下能显著的提高程序的CPU利用率。
前面说,select就像亲自下基层视察的老板,那么epoll这个老板就要显得精明的多了。他可不亲自下基层,他找了个美女秘书,他只要盯着他的秘书看就行了,呸,他只需要听取他的秘书的汇报就行了。汇报啥呢?基层有任何消息,跟秘书说,秘书汇总之后一次性交给老板来处理。这样老板的时间不就大大的提高了嘛。
epoll设计思路简介
(1)epoll在Linux内核中构建了一个文件系统,该文件系统采用红黑树来构建,红黑树在增加和删除上面的效率极高,因此是epoll高效的原因之一。有兴趣可以百度红黑树了解,但在这里你只需知道其算法效率超高即可。
(2)epoll提供了两种触发模式,水平触发(LT)和边沿触发(ET)。当然,涉及到I/O操作也必然会有阻塞和非阻塞两种方案。目前效率相对较高的是 epoll+ET+非阻塞I/O 模型,在具体情况下应该合理选用当前情形中最优的搭配方案。
(3)epoll所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于1024,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以下面语句查看,一般来说这个数目和系统内存关系很大。
系统最大打开文件描述符数
cat /proc/sys/fs/file-max
进程最大打开文件描述符数
ulimit -n
修改这个配置:
sudo vi /etc/security/limits.conf
写入以下配置,soft软限制,hard硬限制
* soft nofile 65536
* hard nofile 100000
缺点:
(1)单进程可以打开fd有限制;
(2)对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低;
(3)用户空间和内核空间的复制非常消耗资源;
poll与select不同的地方:采用链表的方式替换原有fd_set数据结构,而使其没有连接数的限制。
epoll支持的最大链接数是进程最大可打开的文件的数目。
epoll一定优于select吗?什么时候不是?
尽管如此,epoll 的性能并不必然比 select 高,对于 fd 数量较少并且 fd IO 都非常繁忙的情况 select 在性能上反而有优势。
【文章福利】需要C/C++ Linux服务器架构师学习资料加群812855908(资料包括C/C++,Linux,golang技术,内核,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
epol_create
在epoll文件系统建立了个file节点,并开辟epoll自己的内核高速cache区,建立红黑树,建立一个双向链表,用于存储准备就绪的事件。
epoll_create传入一个size参数,size参数只要>0即可,没有任何意义。epoll_create调用函数sys_epoll_create1实现eventpoll的初始化。sys_epoll_create1通过ep_alloc生成一个eventpoll对象,并初始化eventpoll的三个等待队列,