高并发服务的核心机制——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.
只支持非阻塞的读写

相关推荐
就爱敲代码14 分钟前
怎么理解ES6 Proxy
1024程序员节
憧憬一下14 分钟前
input子系统的框架和重要数据结构详解
arm开发·嵌入式·c/c++·1024程序员节·linux驱动开发
三日看尽长安花23 分钟前
【Tableau】
1024程序员节
well_fly37 分钟前
Ubuntu特殊目录
linux·ubuntu
sswithyou43 分钟前
Linux的调度算法
1024程序员节
大熊程序猿1 小时前
ubuntu 安装k3s
linux·运维·ubuntu
武子康1 小时前
大数据-187 Elasticsearch - ELK 家族 Logstash Filter 插件 使用详解
大数据·数据结构·elk·elasticsearch·搜索引擎·全文检索·1024程序员节
luoqice1 小时前
CentOS 自启动某个应用
linux·运维·服务器
互联网杂货铺1 小时前
Python测试框架—pytest详解
自动化测试·软件测试·python·测试工具·测试用例·pytest·1024程序员节
泠山1 小时前
ubuntu增加swap交换空间
linux·运维·ubuntu