下图为epoll的流程图:
![82b5656a214825e19d1af8816807479e.png](https://i-blog.csdnimg.cn/blog_migrate/01ef05ecae8b5cc740719823c2e0eead.jpeg)
epoll一共两种模式,水平触发(LT)和边缘触发(ET),主要的区别在于对读,写数据的处理:
![9a9664504761767ce4788154a4834c4e.png](https://i-blog.csdnimg.cn/blog_migrate/59dd4f523a1fc94d94421c64bd68f979.png)
//LT初始化
epoll_ctrl(connect_socket, EPOLLIN, ADD);
// LT读
void lt_handle_read() {
// 如果读不完,下次epoll_wait一定会返回EPOLLIN
while((n = read(connect_socket, read_buffer)) > 0) {
// read_buffer为当前循环读取到的数据
}
if (n < 0 && errno == EAGAIN) {
// Resource temporarily unavailable, 无数据可读
}
}
// LT写
void lt_handle_write() {
// 一次性发满写缓冲区,这里写满的意图是:判断是否需要添加EPOLLOUT
while((n = write(connect_socket, write_buffer)) > 0) {
// write_buffer为当前循环发送的数据
}
if (write_left == 0) { // 数据发送完毕,删除EPOLLOUT
epoll_ctrl(connect_socket, EPOLLOUT, DELETE);
}
if (n < 0 && errno == EAGAIN) {
// Resource temporarily unavailable, 写缓冲区满了,添加EPOLLOUT
epoll_ctrl(connect_socket, EPOLLOUT, ADD);
}
}
//ET初始化
epoll_ctrl(connect_socket, EPOLLET | EPOLLIN | EPOLLOUT, ADD);
// ET读
void et_handle_read() {
// 这里要把数据读完,否则就是BUG了
while((n = read(connect_socket, read_buffer)) > 0) {
// read_buffer为当前循环读取到的数据
}
if (n < 0 && errno == EAGAIN) {
// Resource temporarily unavailable, 无数据可读
}
}
// ET写
void et_handle_write() {
// 一次性发满写缓冲区
while((n = write(connect_socket, write_buffer)) > 0) {
// write_buffer为当前循环发送的数据
}
if (n < 0 && errno == EAGAIN) {
// Resource temporarily unavailable, 写缓冲区满了,等待可写触发EPOLLOUT
}
}
于是总结出两种模式的优缺点:
![ef20708232a2f16bd75f13c7ff75fa21.png](https://i-blog.csdnimg.cn/blog_migrate/c28e5e970bc2c9142638174e43ebb871.jpeg)