Select、Poll、Epoll 的区别

   1、Select、Poll

  • 每次调用select,先注册回调函数,并需要把fd集合从用户态拷贝到内核态,并在内核态遍历传递进来的所有fd(无可用则睡眠等待)
  • select支持的文件描述符数量默认1024
  • poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构
  • select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次

       2、Epoll        

  • epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd
  • epoll提供了三个函数,epoll_create,epoll_ctl()注册要监听的事件类型、epoll_wait()等待事件的产生、epoll_create()是创建一个epoll句柄

       3、Epoll的优势(参考链接

  • sepoll在每次注册新的事件到epoll句柄中时(在epoll_ctl中指定EPOLL_CTL_ADD),会把所有的fd拷贝进内核,而不是在epoll_wait的时候重复拷贝,保证仅拷贝一次
  • epoll不像select/poll每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍(这一遍必不可少)并为每个fd指定一个回调函数,当设备就绪唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表)。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd(利用schedule_timeout()实现睡一会,判断一会的效果,和select实现中的第7步是类似的)
  • epoll没有fd的数量限制,上限是最大可以打开的文件数目
  • elect,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升
posted @ 2020-09-29 10:20  Ethan_x  阅读(271)  评论(0编辑  收藏  举报