前言
Redis源码中的文件事件轮询,对于linux采用了epoll而非select。故而对epoll产生了兴趣,查资料发现原来epoll比select高效不少。下面是看了几篇文章的一点心得。目前还没真正的看epoll源码,看起来源码比select复杂,等以后有时间在好好啃一啃。
几个关键点
1. epoll是linux独有的。
2. 系统启动的时候,会构建特殊的文件系统。
epfd = epoll_create( MAXEPOLLSIZE );就会在这个虚拟的epoll文件系统里创建一个file结点:kdpfd。可以通过目录查看: /proc/进程id/epfd
3. 系统为epoll在内核的slab高速缓存中分配空间,以红黑树的结构(增删查效率高)存储需要监听的fd信息.
epoll_ctl(int epfd, int op,int fd,struct epoll_event *event);
在文件号为epfd的文件中记录被监听的fd以及监听的事件。epfd文件的数据就是的所在位置就是slab高速缓存,而且还是红黑树的结构。
4. 系统为epoll在内核缓存创建list,记录当前监听的fd中事件已经就绪的fd。
当我们执行epoll_ctl时,除了把fd放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个fd的中断到了,就把它放到准备就绪list链表里。当红黑树上的某fd有事件发生时,内核会出发fd上的回调函数,将fd上的事件加入到list中。
epoll_wait()直接去查询list中的内容。
优势
相比select,epoll的优势:1.epoll_ctl()的调用,将要监听的fd存储到内核空间中,避免了大量fdset的拷贝。select()每次需要对fdset从用户空间拷贝到内核空间。
2.epoll_wait()是直接从判定list是否非空来完成fd事件的查询。而select()是通过遍历maxfd个数的fd,一次调用每个fd的poll函数来查询。
几篇优秀的博客
http://www.cnblogs.com/debian/archive/2012/02/16/2354139.html
http://www.cnblogs.com/debian/archive/2012/02/16/2354469.html
http://www.cnblogs.com/debian/archive/2012/02/16/2354454.html