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平台网络编程的基础吧。