千家信息网

I/O多路复用——epoll

发表于:2024-09-24 作者:千家信息网编辑
千家信息网最后更新 2024年09月24日,epoll是Linux特有的I/O复用函数,它在实现和使用上与select、poll有很大差异。epoll使用一组函数来完成任务,而不是单个函数。epoll把用户关心的文件描述符上的事件放在内核里的一
千家信息网最后更新 2024年09月24日I/O多路复用——epoll

epoll是Linux特有的I/O复用函数,它在实现和使用上与select、poll有很大差异。

epoll使用一组函数来完成任务,而不是单个函数。

epoll把用户关心的文件描述符上的事件放在内核里的一个事件表中,从而无需像select、poll那样每次调用都要重复传入文件描述符集或事件集。

但epoll需要使用一个额外的文件描述符,来唯一标识内核中的这个事件表。


epoll API

epoll有epoll_create、epoll_ctl、epoll_wait三个系统调用。


1.epoll_create

epoll_create创建一个额外的文件描述符,来唯一标识内核中的这个事件表。

1)size参数现在不起作用,只是给内核一个提示,告诉它事件表需要多大。

2)该函数返回的文件描述符将用作其他所有epoll系统调用的第一个参数,以指定要访问的内核事件表。


2.epoll_ctl

epoll_ctl用来操作epoll的内核事件表。

1)fd参数是要操作的文件描述符。

2)op参数指定操作类型,操作类型有如下3种:


EPOLL_CTL_ADD往事件表上注册fd上的事件
EPOLL_CTL_MOD修改fd上的注册事件
EPOLL_CTL_DEL删除fd上注册的事件


3)event参数指定事件,它是epoll_event结构指针类型。

events成员描述事件类型。epoll支持的文件类型和poll基本相同。表示epoll事件类型的宏是在poll对应的宏前加上"E"。但epoll有两个额外的事件类型--EPOLLET和EPOLLONESHOT,它们对于epoll高效运作非常关键。


data成员用于存储用户数据,其类型epoll_data_t定义如下:

epoll_data是一个联合体,其四个成员中使用最多的是fd,它指定事件所从属的目标文件描述符。

ptr成员可用来指定与fd相关的用户数据。但由于epoll_data_t是一个联合体,我们不能同时使用其ptr成员和fd成员,因此,如果要将文件描述符和用户数据关联起来,以实现快速的数据访问,只能使用其他手段,比如放弃使用epoll_data_t的fd成员,而在ptr指向的用户数据中包含fd。


epoll_ctl 成功时返回0,失败返回-1并设置errno。


3.epoll_wait

它在一段超时时间内等待一组文件描述符上的事件。


参数从后往前

1)timeout参数的含义与poll接口的timeout参数相同。

2)maxevents参数指定最多监听多少个事件。

3)epoll_wait函数如果检测到事件,就将所有就绪的事件从内核事件表(由epfd参数指定)中拷贝到它的第二个参数events指向的数组中。这个数组只用于输出epoll检测到的就绪事件,而不像select和poll的数组参数那样既用于传入用户注册的事件,又用于输出内核检测到的就绪事件。这就极大提高了应用程序索引就绪文件描述符的效率。


epoll_wait成功时返回就绪的文件描述符个数,失败时返回-1并设置errno。




LT和ET模式

epoll对文件描述符的操作有两种模式:LT(Level Trigger,水平触发)模式和ET(Edge Trigger,边缘触发)模式。


LT工作模式是默认的工作模式,这种模式下epoll相当于一个效率较高的poll。当epoll_wait检测到其上有时间发生并将此事件通知应用程序后,应用程序可以不立即处理该事件。这样,当应用程序下一次调用eoll_wait时,epoll_wait还会再次向应用程序通告该事件,直到该事件被处理。


当往epoll内核事件表中注册一个文件描述符上的EPOLLET事件时,epoll将以ET模式来操作该文件描述符。ET模式是epoll的高效工作模式。当epoll_wait检测到其上有事件发生并将此通知应用程序后,应用程序必须立即处理该事件,因为后续的epoll_wait调用将不再向应用程序通知这一事件。可见,ET模式在很大程度上降低了同一个epoll事件被重复触发的次数,因此效率要比LT模式高。

--《Linux高性能服务器编程》


LT同时支持block和non-block socket。这种模式中,内核告诉我们一个文件描述符是否就绪了,然后我们可以对这个就绪的fd进行I/O操作。如果我们不做任何操作,内核还是会继续通知我们 。所以,这种模式编程出错的可能性要小一点,传统的select/poll都是这种模式的代表。


ET是高速的工作方式,只支持non-block socket,它的效率要比LT更高。ET与LT的区别在于,当一个新的事件到来时,ET模式下当然可以从epoll_wait调用中获取到这个事件,可是如果这次没有把这个事件对应的套接字缓冲区处理完,在这个套接字中没有新的事件再次到来时,在ET模式下是无法再次从epoll_wait调用中获取这个事件的。而LT模式正好相反,只要一个事件对应的套接字缓冲区还有数据,就总能从epoll_wait中获取这个事件。 因此,LT模式下开发基于epoll的应要简单些,不太容易出错。而在ET模式下事件发生时,如果没有彻底地将缓冲区数据处理完,则会导致缓冲区中的用户请求得不到响应。


Nginx默认使用ET模式来使用epoll。



epoll ET模式为何fd必须要设置为非阻塞

ET(边缘触发)数据就绪只会通知一次,也就是说,如果要使用ET模式,当数据就绪时,需要一直read,直到出错或完成为止。但倘若当前fd为阻塞(默认),那么在当读完缓冲区的数据时,如果对端并没有关闭写端,那么该read函数会一直阻塞,影响其他fd以及后续逻

辑。所以把fd设置为非阻塞,当没有数据的时候,read虽然读取不到任何内容,但是肯定不会被阻塞,那么此时,说明缓冲区数据已经读取完毕,需要继续处理后续逻辑(读取其他fd或者进行wait)。


epoll的优点:

1.支持一个进程打开大数目的socket描述符(fd)。

select的缺点是一个进程打开的fd是有限制的,由FD_SETSIZE指定,默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显然太少了。要解决这个问题,我们一是选择修改这个宏然后重新编译内核,不过资料也同时指出这样会带来网络效率的下降;二是可以选择多进程的解决方案(传统的Apache方案),不过虽然Linux上面创建进程的代价比较小,但仍是不可忽略的 ,加上进程间数据同步远不不上线程间同步高效,所以也不是一种完美的方案。不过epoll则没有这个限制,它所支持的fd上限是最大可以打开文件的数目,这个数字一般远大于2048,这个数目和系统内存关系很大。例如在1GB内存的机器上大约是10w左右,具体数目可以cat /proc/sys/fs/file-max查看。


2.I/O效率不随fd数目增加而下降。

传统的select/poll另一个缺点是当我们拥有一个很大的socket集合,不过由于网络延时,任何时间只有部分的socket是活跃的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的回调函数实现的。


3.使用mmap加速内核与用户空间的消息传递。

无论是select、poll还是epoll都要通过内核把fd消息通知给用户空间,epoll是通过内核与用户空间mmap同一块内存实现的。


使用epoll的tcp服务器,完成简单的HTTP消息回显



用浏览器测试:

事件 模式 文件 内核 数据 参数 用户 应用程序 程序 类型 应用 函数 成员 效率 缓冲区 处理 支持 缓冲 数目 进程 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 相同数据库同一索引 第七史诗哪个服务器是中文 信息安全和网络安全以及 法律软件开发总经理岗位职责 php链接数据库的文件 机房网络安全隐患整改报告 什么是数据库事务日志 电商软件开发龙头公司 网络安全和计算机专业 上海生信分析软件开发 怎么调微信服务器上的聊天记录 嵌入式软件开发难点 sql图书管理员数据库表 网络安全行业管理体系 主题商店显示服务器正忙稍后重试 邯郸大数据软件开发大概多少钱 数据库打开表就自动关闭了 中国期刊数据库是正规网站 数据库安全性博客 sql数据库常用的备份指令 网络安全法从起草到正式出台 服务器的用户管理软件 徐汇区网络技术服务市场价格 三代终端服务器 软件开发行业入行条件 所有网络安全产品的特点和区别 权威服务器解析的过程 无尽挑战高级服务器 数据库软件教程视频 论文查重的数据库引用的是哪里的
0