当前位置: 首页 > ops >正文

epoll_event数据结构及使用案例详解

epoll_event 数据结构详解

在 Linux 的 I/O 多路复用机制 epoll 中,epoll_event 是关键的数据结构,用于描述文件描述符(fd)上的事件和关联数据。其定义在头文件 <sys/epoll.h> 中:

struct epoll_event {uint32_t     events;    // 事件掩码(位图)epoll_data_t data;      // 用户数据(联合体)
};typedef union epoll_data {void    *ptr;    // 自定义指针(常用)int      fd;     // 关联的文件描述符(常用)uint32_t u32;    // 32位整数uint64_t u64;    // 64位整数
} epoll_data_t;
核心字段解析:
  1. events (事件标志位)

    • EPOLLIN:fd 可读(有数据到达)
    • EPOLLOUT:fd 可写(可发送数据)
    • EPOLLERR:fd 发生错误
    • EPOLLHUP:fd 被挂断(对端关闭连接)
    • EPOLLET:启用边缘触发模式(默认水平触发)
    • EPOLLRDHUP:流套接字对端关闭连接(或半关闭)
  2. data (用户数据联合体)

    • 常用 fdptr 存储与事件相关的自定义数据(如连接上下文)

使用案例:基于 ET 模式的 Echo 服务器

以下示例展示 epoll_event 在非阻塞 TCP 服务器中的典型用法(边缘触发模式):

#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>#define MAX_EVENTS 64
#define PORT 8080// 设置 fd 为非阻塞模式
void set_nonblocking(int fd) {int flags = fcntl(fd, F_GETFL, 0);fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}int main() {int server_fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addr = {.sin_family = AF_INET,.sin_port = htons(PORT),.sin_addr.s_addr = INADDR_ANY};// 绑定并监听bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));listen(server_fd, SOMAXCONN);// 创建 epoll 实例int epoll_fd = epoll_create1(0);struct epoll_event ev, events[MAX_EVENTS];// 添加 server_fd 到 epollev.events = EPOLLIN | EPOLLET;  // 边缘触发模式ev.data.fd = server_fd;         // 存储文件描述符epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);while (1) {int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);for (int i = 0; i < nfds; i++) {// 处理新连接if (events[i].data.fd == server_fd) {struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &len);set_nonblocking(client_fd);// 注册客户端 fdev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;ev.data.fd = client_fd;  // 存储客户端 fdepoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);}// 处理客户端数据else if (events[i].events & EPOLLIN) {int client_fd = events[i].data.fd;  // 取出 fdchar buffer[1024];ssize_t bytes_read;// ET 模式需循环读取所有数据while ((bytes_read = read(client_fd, buffer, sizeof(buffer))) {if (bytes_read > 0) {write(client_fd, buffer, bytes_read);  // Echo 回显} else if (bytes_read == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) {close(client_fd);  // 关闭连接break;}}}// 处理连接关闭else if (events[i].events & (EPOLLRDHUP | EPOLLHUP)) {close(events[i].data.fd);  // 关闭失效连接}}}close(server_fd);return 0;
}
关键逻辑说明:
  1. 事件注册

    • 通过 epoll_ctl() 添加 fd 时,初始化 epoll_event 结构:
      ev.events = EPOLLIN | EPOLLET;  // 订阅事件类型
      ev.data.fd = server_fd;          // 存储关联的 fd
      
  2. 事件处理

    • epoll_wait() 返回就绪的 epoll_event 数组
    • 通过 events[i].data.fd 取出关联的 fd
    • 通过 events[i].events 判断具体事件类型
  3. 边缘触发 (ET) 要点

    • 必须循环读写直到返回 EAGAIN
    • 需配合非阻塞 fd 避免阻塞

常见使用技巧

  1. 自定义数据存储

    • 使用 data.ptr 存储复杂结构体(如连接上下文):
      struct connection {int fd;struct sockaddr_in addr;
      };struct connection *conn = malloc(sizeof(*conn));
      conn->fd = client_fd;
      ev.data.ptr = conn;  // 存储指针
      
  2. 事件组合

    • 错误处理:EPOLLERR | EPOLLHUP
    • 读写监听:EPOLLIN | EPOLLOUT
  3. 触发模式选择

    • 水平触发 (LT):未处理事件会持续通知(默认)
    • 边缘触发 (ET):事件就绪时只通知一次(性能更高)

性能提示:ET 模式 + 非阻塞 I/O 是 epoll 高性能的关键组合,适合高并发场景。

http://www.xdnf.cn/news/16249.html

相关文章:

  • 解密负载均衡:如何轻松提升业务性能
  • Qt:qRegisterMetaType函数使用介绍
  • iOS —— 天气预报仿写总结
  • 【日志】unity俄罗斯方块——边界限制检测
  • Zookeeper学习专栏(十):核心流程剖析之服务启动、请求处理与选举协议
  • Java测试题(上)
  • 《设计模式之禅》笔记摘录 - 10.装饰模式
  • gig-gitignore工具实战开发(四):使用ai辅助生成gitignore
  • AI图像编辑能力评测的8大测评集
  • ComfyUI中运行Wan 2.1工作流,电影级视频,兼容Mac, Windows
  • Elasticsearch-9.0.4安装教程
  • 05.原型模式:从影分身术到细胞分裂的编程艺术
  • RAG、Function Call、MCP技术笔记
  • 1 51单片机-C51语法
  • 免模型控制
  • Android Camera setRepeatingRequest
  • c语言-数据结构-沿顺相同树解决对称二叉树问题的两种思路
  • 算法:数组part02: 209. 长度最小的子数组 + 59.螺旋矩阵II + 代码随想录补充58.区间和 + 44. 开发商购买土地
  • KNN算法
  • 构建敏捷运营中枢:打通流程、部署与可视化的智能引擎
  • 【前端工程化】前端项目开发过程中如何做好通知管理?
  • 数仓主题域划分
  • FreeRTOS-中断管理
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘streamlit’问题
  • 与 TRON (波场) 区块链进行交互的命令行工具 (CLI): tstroncli
  • ISAAC ROS 在Jetson Orin NX上的部署
  • Mkdocs相关插件推荐(原创+合作)
  • 目标导向的强化学习:问题定义与 HER 算法详解—强化学习(19)
  • 双非上岸985!专业课140分经验!信号与系统考研专业课140+上岸中南大学,通信考研小马哥
  • Zookeeper 3.6.3【详细技术讲解】整