image.png

int s = socket(AF_INET, SOCK_STREAM, 0);
bind(s, …)
listen(s, …)

//返回一个新的fd,这个fd就是eventpollfs文件系统里的新文件。
//建立红黑树用于保存epoll_ctl传来的需要监听的fd。(select需要每次传递)
int epfd = epoll_create(int size)

//将epoll_event拷贝到内核,转化为epitem,作为节点存入红黑树

epoll_ctl(int epfd, intop, int fd, struct epoll_event *event);

while(1){
//有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回
//当有数据时,还需要将内核就绪事件拷贝到传入参数的events中的用户空间
//当设备上的中断事件来临时这个回调函数会向就绪list链表中插入就绪的fd并唤醒epoll_wait进程。
int n = epoll_wait(…)
for(接收到数据的socket){
//判断事件类型,做相应处理
}
}

epoll优点

  1. 大数目socket描述符

select最大1024

  1. 只返回就绪的socket

select/poll每次调用都会线性轮询扫描全部的fd集合,导致效率呈现线性下降

  1. mmap加速内核用户空间消息传递

    水平触发&边缘触发

    image.png
  • java nio使用水平触发
  • netty使用边缘触发