1 是什么?
在 Linux 系统编程中,epoll_event 是 epoll I/O 多路复用机制的核心数据结构,
定义在 <sys/epoll.h> 头文件中。
它的主要作用是向内核注册需要监听的 I/O 事件,
以及从内核接收已就绪的 I/O 事件。
事件注册:
用于告知内核,程序对某个文件描述符(如 Socket)上的哪些事件(如可读、可写)感兴趣。
事件回传:
当被监控的事件就绪时,
内核会将事件的具体信息和关联的用户数据填充到该结构体中,并返回给程序处理。
2 定义
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events;
epoll_data_t data;
};
events 字段:
一个位掩码(bit mask),
用于指定监控的事件类型。
可以通过位或操作符 | 来组合多个事件。
data 字段:
一个联合体 epoll_data_t,
用于在事件触发时,
将用户自定义的上下文信息返回给程序
events 字段常用事件类型
EPOLLIN
文件描述符可读(如 Socket 有数据到达)。【常用】
EPOLLOUT
文件描述符可写(如 Socket 发送缓冲区未满)。【常用】
EPOLLRDHUP
对端关闭连接或半关闭了写操作(边缘触发模式推荐使用)
EPOLLPRI
有紧急数据可读(如 TCP 带外数据)
EPOLLERR
文件描述符发生错误
EPOLLHUP
挂起
EPOLLET
将监控模式设为边缘触发 (Edge Triggered, ET)。【重要模式】
EPOLLONESHOT
仅监听一次事件,触发后需重新注册(常用于多线程避免惊群)
data 字段:自定义用户数据
data 字段的类型 epoll_data_t 是一个联合体,其常用成员是 fd 和 ptr:
fd:直接存储文件描述符,是最简单的用法。
ptr:存储一个指向自定义复杂结构体的指针。
这在需要为每个连接维护更多上下文信息(如会话状态、缓冲区等)时非常有用,是一种更灵活的用法。
3 epoll_event 的工作流程
epoll_event 主要在两个关键函数中与内核交互:
注册/修改事件 (epoll_ctl):
程序调用 epoll_ctl 并传入一个 epoll_event 结构体指针,
告知内核需监控的 fd 和 events,并可通过 data 字段传递关联信息。
等待/获取事件 (epoll_wait):
程序调用 epoll_wait,当被监控的 I/O 事件就绪,
内核会将这些已触发的事件信息填充到用户提供的 epoll_event 数组中进行回传。
4 总结
epoll_event 是用户空间与 Linux 内核 epoll 机制交互的“契约载体”:
传入时:告诉内核“我关心什么事件 + 用什么标识符关联它”
返回时:内核告诉你“哪些事件已就绪 + 你当初绑定的标识符是什么”