全部博文(135)
分类:
2011-08-11 14:58:41
简述EPOLL
2008-08-07 12:54
1,epoll为啥高效
TCP协议栈发现一个socket有事件发生时,它就会唤醒阻塞中的进程(调用select、poll、epoll_wait而睡眠的应用程序)。区别在于,select和poll的内核实现中,协议栈仅仅是唤醒应用程序,没有其他后续操作,所以select内部醒来后还得自己轮询所有的socket;当socket的数量很大时,这里的效率就有了瓶颈。
epoll不同,在内核支持epoll后,唤醒应用程序的操作中,可以挂载回调函数,所以epoll实现的回调函数就把发生事件的socket信息记录到一个就绪队列中了。当epoll_wait醒来的时候,它当然不需要轮询,直接就从就绪队列中就可以取出所有发生了事件的套接字。
这里面,显然有计算机中中断和轮询的思想在。
2,ET和LT
简单地说,LT的套接字从就绪队列中取出后,如果该套接字上确实是有事件,那么内核还会将它再入放入就绪队列,下次epoll_wait还会返回该套接字。ET就不一样,从就绪队列中取出来后就不会再放进去了,除非TCP协议栈再次因为有了新事件再次将其放入队列。
这样导致的差别是LT的套接字不会发生“饿死”的现象,比如说LT的套接字收到了10000个字节的数据,那么你每次read 100个字节后继续epoll_wait,该套接字的事件依然会被返回(因为每次epoll_wait时,内核发现数据没有读完,依然会让该套接字保持在就绪队列中),不管有没有新的数据到达。ET就不一样,如果你读了100字节后就继续epoll_wait,只要没有新数据(或事件)到达,那么就永远不会监听到该套接字的事件了。所以ET的套接字常常设置为非阻塞的,在epoll_wait返回后一次性读完,直到返回EAGAIN为止。LT的套接字当然最好也设置为非阻塞的。
3,结论
写技术文章是件很麻烦的事,不知道说明白没有,EPOLL的关键是在内核里设置了一个“就绪队列”以及回调函数机制。
Pasted from <http://hi.baidu.com/nanpo/blog/item/20b702241b73a92dd5074277.html>