[TOC]
概述
在网络编程中,会涉及到水平触发与边缘触发的概念,工程中以边缘触发较为常见,本文讲述了边缘触发与水平触发的概念,并给出代码示例,通过代码可以很清楚的看到它们之间的区别。
水平触发与边缘触发
水平触发(level-trggered)
- 只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知,
- 当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知
边缘触发(edge-triggered)
- 当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知,
- 当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知
两者的区别?
水平触发是只要读缓冲区有数据,就会一直触发可读信号,而边缘触发仅仅在空变为非空的时候通知一次,举个例子:
- 读缓冲区刚开始是空的
- 读缓冲区写入2KB数据
- 水平触发和边缘触发模式此时都会发出可读信号
- 收到信号通知后,读取了1kb的数据,读缓冲区还剩余1KB数据
- 水平触发会再次进行通知,而边缘触发不会再进行通知
所以边缘触发需要一次性的把缓冲区的数据读完为止,也就是一直读,直到读到EGAIN
(EGAIN
说明缓冲区已经空了)为止,因为这一点,边缘触发需要设置文件句柄为非阻塞。
ET模式在很大程度上减少了epoll事件被重复触发的次数,因此效率要比LT模式高。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
这里只简单的给出了水平触发与边缘触发的处理方式的不同,边缘触发相对水平触发处理的细节更多一些,
1 | //水平触发, 如果这次从 fd 中没有将所有的字节读完,那么这个 fd 就还会再次唤醒 |
参考
代码: cpp/io/epollet/server.c