epoll --水平触发与边缘触发
epoll 提供了边沿触发 (ET) 和电平触发 (LT)的事件触发方式。两种机制的区别如下:
先假设出现如下情况:
- 某个有一个管道已经建立连接,fd加入了epoll中,监测可读事件。
- 管道的写入者,写入了2KB的数据。
- 读取者调用epoll_wait()成功返回了事件。
- 但是管道的读取者只读取了1KB 的数据。
- 读取者读取结束,再次调用epoll_wait()
如果用户在添加fd到epoll时,使用了参数EPOLLET(边缘触发)。 当读线程执行第5步的时候,线程可能会被挂起,尽管缓冲区汇总还存在数据,与此同时远端可能在等待当前线程的相应。边缘触发就是套接字的状态改变时才触发,具体说就是从不可读到切换到可读的这一瞬间才会触发。所以可能会导致第5步被永久的阻塞。
使用边缘触发时,应该避免使用阻塞的套接字,以避免部分的套接字被饿死。具体建议如下:
1、使用非阻塞的文件描述符
2、只有当read或write返回EAGAIN以后,才再次调用wait(就是数据全部读写完成了)。
水平触发模式是默认的模式。
优点:
当多个线程或进程同时wait同一个epoll时,如果设置了边缘触发,可以避免出现“惊群”效应,把所有的线程都唤醒了。