Linux平台的epoll通信模型
·概要:
Epoll是在linux2.6内核中加入的作为处理大批量句柄而改进的poll。这是Linux平台的处理异步I/O的高效模型。
记得在网上看过一个资料说:select就像是鬼子进村时一遍遍的询问"鬼子进村了么?",而epoll则像是派出一个人监视鬼子是否进村了。虽然现在还不能通过两者体会select和epoll的本质不同,暂且记录下来。
·要点:
基础:
--原理:
epoll适用的模型是Reactor设计模式--可通过Reactor深入理解。
相比于IOCP,epoll仅仅是一个异步事件通知机制,本身并不做任何的I/O操作而是会得到可以进行I/O操作的通知。而IOCP不仅是在I/O操作完成后在进行通知同时通过内部的线程池封装了一部分I/O控制逻辑。
因此epoll是串行处理,同时可以通过配合线程池来发挥最大作用。
--头文件:
#include <sys/epoll.h>
--数据结构:
typedef union epoll_data{
void * ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
}epoll_data_t;
struct epoll_event{
__uint32_t events;
epoll_data_t data;
};
其中可以通过epoll_data中的ptr传递应用层数据;
--接口函数:
用到的接口函数有:epoll_create(),epoll_ctl(),epoll_wait():
epoll_create函数:
原型:int epoll_create(int size);
功能:生成一个epoll专用的文件描述符。
参数:指定生成描述符的最大范围--参数的设定没有好的参考。
epoll_ctl函数:
原型:int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event);
功能:可注册、修改、删除epoll事件。
返回值:成功返回0,否则返回-1.
参数:epfd是epoll_create()创建的epoll句柄,op取值{EPOLL_CTL_ADD,
EPOLL_CTL_MOD,EPOLL_CTL_DEL}的操作,fd是关联事件的对象,
event则是轮询时被通知的时间类型。
epoll_wait函数:
原型:int epoll_wait(int epfd,struct epoll_event* events,
int maxevents,int timeout);
功能:进行I/O就绪轮询操作。
返回值:就绪的时间数目--即events数组的大小。
参数:epfd是epoll句柄,events是就绪的事件数组,maxevents则是每次
可处理的event的最大数目--不能比epoll_create(int size)中参数size
大,timeout则是超时控制。
--说明:
首先需要说明的是epoll句柄也是系统资源,在使用完后需要close()释放资源。
其次需要说明的是event_data中event的取值:
EPOLLIN--可读(包括对端SOCKET正常关闭)
EPOLLOUT--可写
EPOLLPRI--有紧急数据可读(表示有带外数据到来)
EPOLLERR--发生错误
EPOLLHUP--被挂断
EPOLLET--边缘触发模式
EPOLLONESHOT--只监听一次,当监听完这次事件后如需要继续监听的话
还需要再次将SOCKET加入到EPOLL队列中。
epoll有两种工作方式:
LT(level triggered)是缺省方式,同时支持block和no-block。
特点是如果不处理事件的话会持续进行通知—与select/poll一样;
ET(edge triggered)是高速方式,只支持no-block socket。
特点是只通知一次就绪事件然后假设不需要在提示。
--常用模型:
首先要创建并配置epoll句柄;
然后创建一个监听socket并注册到epoll中;
最后进入一个{调用epoll_wait==》处理就绪事件}的循环中。
其中,可以在处理就绪事件过程中将处理交给线程池做来进行扩展。
·小结:
有很多库(知道的有boost.asio和libevent)在linux平台都是基于epoll的。
EPOLL算是Linux平台网络编程的基础吧。