Gary Kildall

导航

SOKET编程系列 epoll 原理(1) epoll实现

首先上图关于epoll的两种模式

LT: 水平触发模式----> 只要有(注册过的)描述符就绪(可读/可写),都可通过epoll_wait返回

ET: 边缘触发模式----> 仅仅在返回(注册过的)描述符状态变化的(之前是不可读/不可写 突然编程可读/可写)的状态的,才会由epoll_wait返回  :::(这模式可不接受阻塞的描述符)

简述:LT模式跟select效率差不多,ET模式在网络阻塞严重的时候,或者IO阻塞严重的时候效率十分之高(不然比select都要低)

                              盗图:下图来自博客 http://blog.csdn.net/weiyuefei/article/details/52242778

 

                            Epoll工作模式概述

 

(1) epoll_wait()调用 ep_poll等待,ready_fd_List(就绪描述符队列)为空挂起当前进程,阻塞在epoll_wait()。

(2)有fd变为可读或者可写(缓冲区buffer,有不可读/不可写 ---> 可读/可写),fd状态改变导致ep_poll_callback()调用起来,将对应的fd(其实是fd对应的epollItem)放到到ready_fd_List(就绪描述符队列)

(3)ready_fd_List不是空,唤醒进程,epoll_wait函数继续执行((4),(5)都是epoll_wait的过程)。

(4)然后epoll、内部调用 ep_events_transfer 将ready_fd_List里面的epollItem取出来(ready_fd_List清空),放到txtList当中。

(5)(关键)调用ep_send_events()函数, (看蓝色线)扫描txtList的epItem函数,调用描述符对应的fd的poll方法,(这个时候值调用较新的events,防止之前的event被更新),

    最后将对应的events与fd一起发送到用户空间(封装在struct epoll_event,从epoll_wait返回)。这是后ET和LT的区别来了,如果是LT模式这个event 仍然是用户关心的

    (读缓冲区还没读完/写缓冲区没有写干净)就会将其fd放置回去ready_fd_List(就绪描述符队列),如果是ET那就不加进去咯。

 

epoll的ET与LT其实就是一步之遥啊(最后是否将fd加回去ready_fd_List里面)。

(1)epoll_wait返回的条件就是ready_fd_List不为空,两种情况,描述符被改变状态了(不可读/不可写-->可读/可写)看图中红线,或者描述符被重复放置到ready_fd_List当中(描述符还有缓冲区数据可用)蓝线。

(2)注意 描述符改变这种状况是通用语ET与LT模式的(红线通用),但是描述符被重新加到ready_fd_List的这种情况只适用于LT模式(蓝线只用于LT)。

详解描述符状态change与重复假如描述符的状态

红线 (描述符改变):

同时满足1-2

读状态 --------- (1)fd对应的缓冲区由不可读--->可读的时候,有数据来,缓冲区由空变有

    --------- (2)准备写过来的新数据来了,需要写的数据来了

写状态 --------- (1)fd对应的可写缓冲区满 --->不满,缓冲区满了,写了一部分,漏了一点空位出来

    --------- (2)有东西有写出去了

 

蓝线 (描述符重新进入)

读状态 ---------  (1)缓冲区仍然有数据中有数据可读的时候,即buffer不空的时候fd的events的可读为就置1。

写状态 ----------  (1)仍然有数据要写,但是epoll_wait之后写完缓冲区之后,仍然有数据,就是上一次缓冲区已经满了,即buffer不满的时候fd的events的可写位就置1。

     

 

posted on 2016-10-23 23:46  Gary Kildall  阅读(178)  评论(0)    收藏  举报