后台开发,网络交互是必须的,而epoll基本绝大多数网络框架的必备武器,本文对epoll进行详细的介绍,包括epoll的作用,优点,接口,实现原理等。
一. epoll是什么
epoll是一种IO多路转接技术,在LINUX网络编程中,经常用来做事件触发,即当有特定事件到来时,能够检测到,而不必阻塞进行监听。
epoll有两种工作方式,ET-水平触发 和 LT-边缘触发(默认工作方式),主要的区别是:
LT,内核通知你fd是否就绪,如果没有处理,则会持续通知。而ET,内核只通知一次。
二. epoll的优点
与select相比,epoll有以下优点:
2.1. 支持进程打开大量数目的socket描述符,select支持的进程描述符由FD_SETSIZE设置,默认值为
1024,而epoll不受这个限制。
2.2. epoll的效率,不随监听的socket数目增加而线性下降。
select采用轮询的方式,对socket集合的描述符表进行扫描,如果socket数量过大,并且大多数
socket属于idle状态,select的扫描就做了很多无用功。
epoll只会对活跃的socket进行操作,所以,在socket数量比较大,而绝大多数socket属于idle
状态时,epoll的效率会远胜于select。如果绝大多数socket是活跃的,由于epoll_ctl的影响,
epoll的效率会稍微比select差。
3.3. 使用mmap加速内核与用户空间的传递,关于mmap,找个时间做个详细的介绍。
三. epoll的接口
epoll主要有三个接口
3.1 int epoll_create( int size )
创建一个epoll的句柄,size表示监听的数目一共有多大,我们现网的服务器,每个进程是设置
12W。
3.2 int epoll_ctl( int epfd, int op, int fd, struct epoll_event* event )
事件注册函数,epfd是epoll_create返回的句柄,op是表示做什么动作,用三个宏表示:
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
fd表示要监听的描述符,event表示内核要监听什么事,由以下几个宏表示:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读;
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把
这个socket加入到EPOLL队列里
3.3 int epoll_wait( int epfd, struct epoll_event* events, int maxevents, int time_out )
等待事件的发生。events,存储epoll_wait操作完成后,存储的事件。maxevents表示当前要监听的
所有socket句柄数。time_out为超时时间。返回值表示需要处理的事件数目,0表示超时。
四. epoll的实现原理
epoll_create
在epoll文件系统建立了个file节点,并开辟epoll自己的内核高速cache区,建立红黑树,分配
好想要的size的内存对象,建立一个list链表,用于存储准备就绪的事件。
epoll_ctl
把要监听的socket放到对应的红黑树上,给内核中断处理程序注册一个回调函数,通知内核,如果
这个句柄的数据到了,就把它放到就绪列表。
epoll_wait
观察就绪列表里面有没有数据,并进行提取和清空就绪列表,非常高效。
LT和ET实现的区别?
由epoll_wait进行实现,如果是LT模式,它发现soket上还有未处理的事件,则在清理就绪列表
后,重新把句柄放回刚刚清空的就绪列表。
如果所示,红黑树,就绪列表,小段cache,就解决了大并发的问题,果然是简单才是美。
本文出自 “思考沉淀” 博客,请务必保留此出处http://joezhengjinhong.blog.51cto.com/7791846/1564987
原文地址:http://joezhengjinhong.blog.51cto.com/7791846/1564987