高并发服务的核心机制——IO多路转接--->epoll

目录

引言

三个系统调用

epoll模型

epoll工作方式


引言

epoll是在Linux内核里重新添加的一套机制,它是在2.5.44内核中被引进的epoll(4),它可以批量的监控文件描述符的各种事件。

三个系统调用

在头文件#include <sys/epoll.h>中

cpp 复制代码
 int epoll_create(int size);

用于创建epoll模型,返回值是一个文件描述符,也可以理解为epoll模型的一个句柄(Linux里一切接文件)。这个epoll模型是什么后文详细介绍。在Linux2.6.8之后epoll_create的参数是被忽略的,我们只需传入一个非负整数即可。

cpp 复制代码
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

第一个参数:传入epoll模型对应的文件描述符
第二个参数:传入对epoll模型的操作

|--------------------------------|
| EPOLL_CTL_ADD :注册新的fd到epfd中; |
| EPOLL_CTL_MOD :修改已经注册的fd的监听事件; |
| EPOLL_CTL_DEL :从epfd中删除一个fd; |

第三个参数:要监控的文件描述符

第四个参数:要监控的事件
struct epoll_event 结构如下

cpp 复制代码
typedef union epoll_data
{
    void *ptr;          // 指向用户自定义数据的指针
    int fd;            // 文件描述符
    uint32_t u32;      // 32 位整数
    uint64_t u64;      // 64 位整数
} epoll_data_t;

struct epoll_event
{
    uint32_t events;    // 发生的事件
    epoll_data_t data;  // 用户数据
} __EPOLL_PACKED;      // 确保本结构体不被填充
  • events (uint32_t):

    • 这个字段指定了关注的事件类型,比如 EPOLLIN(可读事件)、EPOLLOUT(可写事件)等。可以使用按位或运算组合多个事件。
  • data (epoll_data_t):

    • 这个字段是一个联合体,允许存储不同类型的数据。通常用来保存与事件关联的文件描述符或者指向用户结构的指针。你可以使用以下方式之一来存储数据:
      • ptr: 通用指针,指向用户自定义的数据结构。
      • fd: 文件描述符。
      • u32u64: 32 位和 64 位整数,可以用于存储任意附加信息。

events可以是以下几个宏的集合:
EPOLLIN : 表示对应的文件描述符可以读 (包括对端SOCKET正常关闭);
EPOLLOUT : 表示对应的文件描述符可以写;
EPOLLPRI : 表示对应的文件描述符有紧急的数据可读 (这里应该表示有带外数据到来);
EPOLLERR : 表示对应的文件描述符发生错误;
EPOLLHUP : 表示对应的文件描述符被挂断;
EPOLLET : 将EPOLL设为边缘触发(Edge Triggered)模式, 这是相对于水平触发(Level Triggered)来说的.
EPOLLONESHOT :只监听一次事件, 当监听完这次事件之后, 如果还需要继续监听这个socket的话, 需要再次把这个socket加入到EPOLL队列里

cpp 复制代码
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

参数events是分配好的epoll_event结构体数组.
epoll将会把发生的事件赋值到events数组中 (events不可以是空指针,内核只负责把数据复制到这个events数组中,不会去帮助我们在用户态中分配内存).
maxevents告之内核这个events有多大,这个 maxevents的值不能大于创建epoll_create()时的size.
参数timeout是超时时间 (毫秒,0会立即返回,-1是永久阻塞).
如果函数调用成功,返回对应I/O上已准备好的文件描述符数目,如返回0表示已超时, 返回小于0表示函数失败.

epoll模型

当某一进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体。要监控的事件被连入到内核的红黑树结构中。

当就有文件描述符上的事件就绪了,epoll模型中还有一个双向链表结构,这个数据结构用来存放就绪事件,epoll_wait就是在这上面捞取就绪事件。

epoll工作方式

epoll有2种工作方式-水平触发(LT)和边缘触发(ET)。
水平触发Level Triggered 工作模式
epoll默认状态下就是 LT 工作模式 .
当epoll 检测到 socket 上事件就绪的时候 , 可以不立刻进行处理 . 或者只处理一部分 .
如上面的例子 , 由于只读了 1K 数据 , 缓冲区中还剩 1K 数据 , 在第二次调用 epoll_wait 时 , epoll_wait
仍然会立刻返回并通知 socket 读事件就绪 . 直到缓冲区上所有的数据都被处理完, epoll_wait 才不会立刻返回 .
边缘触发Edge Triggered 工作模式
如果我们在第1 步将 socket 添加到 epoll 描述符的时候使用了 EPOLLET 标志 , epoll 进入 ET 工作模式 .
当epoll 检测到 socket 上事件就绪时 , 必须立刻处理 .
如上面的例子, 虽然只读了 1K 的数据 , 缓冲区还剩 1K 的数据 , 在第二次调用 epoll_wait 的时候 ,
epoll_wait 不会再返回了 . 也就是说, ET 模式下 , 文件描述符上的事件就绪后 , 只有一次处理机会 .
ET的性能比 LT 性能更高 ( epoll_wait 返回的次数少了很多 ). Nginx 默认采用 ET 模式使用 epoll.
只支持非阻塞的读写

相关推荐
耗同学一米八23 分钟前
2026年河北省职业院校技能大赛中职组“网络建设与运维”赛项答案解析 1.系统安装
linux·服务器·centos
知星小度S1 小时前
系统核心解析:深入文件系统底层机制——Ext系列探秘:从磁盘结构到挂载链接的全链路解析
linux
2401_890443021 小时前
Linux 基础IO
linux·c语言
智慧地球(AI·Earth)2 小时前
在Linux上使用Claude Code 并使用本地VS Code SSH远程访问的完整指南
linux·ssh·ai编程
老王熬夜敲代码3 小时前
解决IP不够用的问题
linux·网络·笔记
zly35003 小时前
linux查看正在运行的nginx的当前工作目录(webroot)
linux·运维·nginx
QT 小鲜肉4 小时前
【Linux命令大全】001.文件管理之file命令(实操篇)
linux·运维·前端·网络·chrome·笔记
问道飞鱼4 小时前
【Linux知识】Linux 虚拟机磁盘扩缩容操作指南(按文件系统分类)
linux·运维·服务器·磁盘扩缩容
egoist20235 小时前
【Linux仓库】超越命令行用户:手写C语言Shell解释器,解密Bash背后的进程创建(附源码)
linux·c语言·bash·xshell·环境变量·命令行参数·内建命令
Lenyiin5 小时前
《 Linux 修炼全景指南: 八 》别再碎片化学习!掌控 Linux 开发工具链:gcc、g++、GDB、Bash、Python 与工程化实践
linux·python·bash·gdb·gcc·g++·lenyiin