注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

EPOLL的小总结  

2012-04-11 11:41:08|  分类: 网络服务编程技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

EPOLL的小总结

一、Epoll网络模型在IO的多路复用了使用了同步和异步两种方式,在LINUX中叫做前摄器和反应器。

这两种IO多路复用模式:Reactor和Proactor的详细说明,见服务编程中的  , “高性能I/O设计Reactor和Proactor”以及  “Proactor和Reactor模式_继续并发系统设计的扫盲”两篇博文。

二、ET、LT高速模式和默认模式

EPOLLLT——水平触发(LT,这种是默认的方式)
EPOLLET——边缘触发(ET,高速模式)
epoll有EPOLLLT和EPOLLET两种触发模式,LT是默认的模式,ET是“高速”模式。LT模式下,只要这个fd还有数据可读,每次 epoll_wait都会返回它的事件,提醒用户程序去操作,而在ET(边缘触发)模式中,它只会提示一次,直到下次再有数据流入之前都不会再提示了,无 论fd中是否还有数据可读。所以在ET模式下,read一个fd的时候一定要把它的buffer读光,也就是说一直读到read的返回值小于请求值,或者 遇到EAGAIN错误。

 

三、epoll的这个东西在LINUX上应用还是比较广泛的,其实他很简单,主要有以下几个函数:
1. int epoll_create(int size);
创 建一个epoll的句柄,他的参数跟select模型中的参数有一定的区别,(SELECT是给出最大监听的fd+1的值) 需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在 使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

这个函数的参数,在内核版本LINUX2.6.8后就没有什么具体的意义了,只要大于0即可。
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll的事件注册函数,它不同与select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。第一个参数是epoll_create()的返回值,第二个参数表示动作,用三个宏来表示:
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:

typedef union epoll_data {

    void *ptr;

    int fd;//网络编程中主要使用这个参数

    __uint32_t u32;

    __uint64_t u64;

} epoll_data_t;


struct epoll_event {
  __uint32_t events;  /* Epoll events */
  epoll_data_t data;  /* User data variable */
};
events可以是以下几个宏的集合:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
epoll_ctl用来添加/修改/删除需要侦听的文件描述符及其事件,epoll_wait/epoll_pwait接收发生在被侦听的描述符上的,用户感兴趣的IO事件。epoll文件描述符用完后,直接用close关闭即可,非常方便。事实上,任何被侦听的文件符只要其被关闭,那么它也会自动从被侦听的文件描述符集合中删除,很是智能。

每次添加/修改/删除被侦听文件描述符都需要调用epoll_ctl,所以要尽量少地调用epoll_ctl,防止其所引来的开销抵消其带来的好处。有的时候,应用中可能存在大量的短连接(比如说Web服务器),epoll_ctl将被频繁地调用,可能成为这个系统的瓶颈。
3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
等 待事件的产生,类似于select()调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个 maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有 说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。

再执行该函数成功后,进行连接处理过程中,来的新的连接请求,将加入下一次处理的集合中。

    在许多测试中我们会看到如果没有大量的idle-connection或者dead-connection,epoll的效率并不会比select/poll高很多,但是当我们遇到大量的idle-connection(例如WAN环境中存在大量的慢速连接),就会发现epoll的效率大大高于select/poll。

 

四、EPOLL的优势和劣势

select模型受限于 FD_SETSIZE即进程最大打开的描述符数linux2.6.35为1024,而EPOLL没有这个限制,但前面所说的,当短连接过多和连接数量少时,未必EPOLL有优势,EPOLL的优势在于WAN中存在大量的慢速连接,此时他的性能是非常棒的。

其它的诸如内核句柄的管理,内核的调优,句柄无需扫描等等,都可以在其它的资料或者博客的其它文章查看。

雨里深山雪上烟,看来容易做时难。

  评论这张
 
阅读(1421)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017