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) 收藏 举报
浙公网安备 33010602011771号