多路复用epoll

Epoll:性能之王(红黑树+回调)

epoll 是为了解决大批量句柄处理而设计的

一、 Epoll 的核心工作原理

要理解 Epoll 的接口,首先要理解它在内核里建立的两个"秘密基地":

  1. 红黑树 (Red-Black Tree, rbr**)**:
    • 用来存储所有你想要监听的文件描述符(FD)。
    • select 每次都要把整个集合传给内核,而 Epoll 把这些 FD 存在内核的红黑树里,不需要重复拷贝 。增删查改的效率是 O(logN)
  1. 就绪双向链表 (Ready List, rdlist**)**:
    • 用来存储已经就绪(有数据来了)的事件。
    • 当网卡接收到数据,会触发回调函数 (ep_poll_callback),这个回调函数会自动把活跃的 FD 放入这个链表 5。
    • epoll_wait 不需要遍历所有连接,只需要检查这个链表是否为空即可,复杂度是 O(1)

二、 Epoll 的三个核心接口详解

Epoll 把 select 那个臃肿的一个函数拆分成了三个步骤,分别对应"建群"、"加人"、"等消息" 。

1. epoll_create ------ 创建管家(建群)
复制代码
int epoll_create(int size);
  • 功能 :创建一个 Epoll 的句柄(在内核中创建一个 eventpoll 对象)。
  • 参数 size
    • 这个参数其实是被忽略的,只要填一个大于 0 的数即可 。
  • 返回值 :成功返回一个 epoll 的文件描述符(epfd),失败返回 -1。
  • 注意 :Epoll 句柄本身也是一个文件描述符,占用一个 FD 资源,用完后必须调用 close() 关闭 。
2. epoll_ctl ------ 管理名单(加人/踢人)

这是 Epoll 与 Select 最大的不同点。Select 是在等待时才给名单,Epoll 是提前注册

复制代码
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  • 参数详解
    • epfdepoll_create 返回的那个句柄 。
    • op:要进行的操作动作,用宏表示 :
      • EPOLL_CTL_ADD:注册新的 FD 。
      • EPOLL_CTL_MOD:修改已有的 FD 监听事件 。
      • EPOLL_CTL_DEL:从红黑树中删除一个 FD 。
    • fd:需要监听的 socket 文件描述符 。
    • event:告诉内核你要监听什么事(读/写/异常)以及你留的"备注数据" 。

关键结构体 epoll_event

复制代码
struct epoll_event {
uint32_t     events;      // 监听的事件类型
epoll_data_t data;        // 用户数据(给用户自己用的)
};
    • events****取值
      • EPOLLIN:可读(包括对端关闭)。
      • EPOLLOUT:可写 。
      • EPOLLET开启边缘触发模式 (Edge Triggered)
    • data****联合体 : 这是一个联合体,你可以存 int fd,也可以存 void *ptr 指针。当事件就绪时,内核会把这个 data 原样还给你。
3. epoll_wait ------ 等待消息(收割)
复制代码
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
  • 功能 :收集在 Epoll 监控中已经发生的事件 。它直接查看内核的 rdlist 就绪链表,如果有数据,就拷贝给用户。
  • 参数详解
    • epfd:Epoll 句柄。
    • events输出参数。这是一个数组,内核会把就绪的事件复制到这里 。
    • maxevents:告诉内核这个数组有多大(不能大于创建时的 size,但现在 size 被忽略,主要是防止数组越界)。
    • timeout:超时时间(毫秒)。0 表示立即返回(非阻塞),-1 表示永久阻塞,>0 表示等待指定时间 。
  • 返回值
    • > 0:就绪的文件描述符个数。
    • 0:超时。
    • -1:出错 。

三、 Epoll 的两种工作模式:LT vs ET

1. LT 模式 (Level Triggered) ------ 水平触发
  • 默认模式
  • 机制 :只要 socket 接收缓冲区里还有数据,epoll_wait 就会一直通知你 。
  • 例子 :缓冲区有 2KB 数据,你只读了 1KB。下次调用 epoll_wait,它会再次返回并告诉你"有数据读" 。
  • 特点:支持阻塞和非阻塞读写,编程不容易出错 。Select 和 Poll 本质上也是 LT 模式 。
2. ET 模式 (Edge Triggered) ------ 边缘触发
  • 高性能模式(Nginx 默认采用)。
  • 机制:只有当状态发生变化时(从无数据变成有数据),内核才会通知一次 。
  • 例子 :缓冲区有 2KB 数据,你只读了 1KB。下次调用 epoll_wait它不会再通知你了 ,剩下的 1KB 数据会一直待在缓冲区里,直到下一次有数据到来 。
  • 要求
    1. 必须配合 非阻塞 I/O (Non-blocking IO) 使用 。
    2. 必须使用循环 (while) 读取,直到 read 返回 EAGAIN 错误,确保把缓冲区读空 。
  • 优点 :减少了 epoll_wait 返回的次数,系统调用开销更小 。
相关推荐
M158227690555 小时前
TCP转LORA产品说明及应用案例
网络·网络协议·tcp/ip
旖旎夜光6 小时前
Linux(13)(中)
linux·网络
来可电子CAN青年6 小时前
CAN总线远距离传输老断网?Fx灯不闪别慌,这几招让你的通信“稳如泰山”!
网络
独行soc6 小时前
2026年渗透测试面试题总结-18(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
云小逸6 小时前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
自不量力的A同学6 小时前
Solon AI v3.9 正式发布:全能 Skill 爆发
java·网络·人工智能
威迪斯特6 小时前
CentOS图形化操作界面:理论解析与实践指南
linux·运维·centos·组件·图形化·桌面·xserver
一方热衷.6 小时前
在线安装对应版本NVIDIA驱动
linux·运维·服务器
独自归家的兔6 小时前
ubuntu系统安装dbswitch教程 - 备份本地数据到远程服务器
linux·运维·ubuntu
ONE_SIX_MIX6 小时前
ubuntu 24.04 用rdp连接,桌面黑屏问题,解决
linux·运维·ubuntu