参考 https://blog.csdn.net/weixin_44754615/article/details/120879370
阻塞io
epoll高效的本质在于:
减少了用户态和内核态的文件句柄拷贝
减少了对可读可写文件句柄的遍历
mmap 加速了内核与用户空间的信息传递,epoll是通过内核与用户mmap同一块内存,避免了无谓的内存拷贝
IO性能不会随着监听的文件描述的数量增长而下降
使用红黑树存储fd,以及对应的回调函数,其插入,查找,删除的性能不错,相比于hash,不必预先分配很多的空间
维护了一个监听socket的红黑树
还有一个通过网卡 使用中断程序把已经准备好的socket fd放到 双向链表中 然后 唤醒阻塞在eventpoll中的进程来进行处理。
EPOll的ET与LT?
epoll事件有两种模型,边沿触发:edge-triggered (ET), 水平触发:level-triggered (LT)
水平触发(level-triggered)
socket接收缓冲区不为空 有数据可读 读事件一直触发
socket发送缓冲区不满 可以继续写入数据 写事件一直触发
边沿触发(edge-triggered)
socket的接收缓冲区状态变化时触发读事件,即空的接收缓冲区刚接收到数据时触发读事件
socket的发送缓冲区状态变化时触发写事件,即满的缓冲区刚空出空间时触发读事件
边沿触发仅触发一次,水平触发会一直触发。
et和lt 直观解释
ET是一次事件只会触发一次,如一次客户端发来消息,fd可读,epoll_wait返回.等下次再调用epoll_wait则不会返回了
LT是一次事件会触发多次,如一次客户端发消息,fd可读,epoll_wait返回,不处理这个fd,再次调用epoll_wait,立刻返回,
ET是每次读写完就删除红黑树ctl函数执行监听的socket
LT是需要手动的删除监听的socket
比如写的场景 需要写1M内容缓冲区是5k 那么et会一直写 直到写完 然后自动删除 监听socket。这是ET模式
但是读的场景如果大量内容读会产生其他socket线程饥饿问题因为他会一直读到结束 然后删除监听 ,如果有需要再次监听重新ctl
LT就是读的时候读固定大小然后 下次循环的时候在读 不会产生饥饿
写的时候同样也是 写完之后 没有东西写了 如果没有 手动删除ctl红黑树内容 就会wait函数的时候 还会收到就绪的fd。
网友评论