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

网络编程——多路复用——epoll机制

理解 epoll:高效的 Linux I/O 多路复用机制

在网络编程中,处理多个并发连接是一个常见的挑战。传统的方式通常使用阻塞式 I/O 或者多线程/多进程来处理并发连接,但这些方法都存在一些性能和资源管理的问题。为了解决这些问题,Linux 引入了 epoll 这一高效的 I/O 多路复用机制。本文将详细介绍 epoll 的原理、用法和优势。

什么是 epoll?

epoll 是 Linux 操作系统提供的一种 I/O 多路复用机制,用于监视多个文件描述符的状态并进行事件驱动的 I/O 操作。它是基于事件驱动的模型,通过将文件描述符注册到 epoll 内核事件表中,然后等待内核通知有事件发生,从而避免了阻塞式 I/O 和传统的轮询方式。epoll 可以同时处理大量的并发连接,并且能够高效地处理文件描述符上的事件。

epoll 的优势

相比传统的 select 和 poll,epoll 具有以下优势:

  1. 高效:epoll 使用了更加高效的数据结构和算法,能够在大规模并发连接下提供更好的性能。
  2. 扩展性:epoll 支持水平触发和边缘触发两种模式,可以根据应用的需求选择不同的触发模式。
  3. 节省资源:epoll 使用一个文件描述符来管理多个连接,而不是每个连接都需要一个文件描述符,从而节省了资源。
  4. 没有连接数限制:epoll 没有连接数的限制,可以处理成千上万个并发连接。
  5. 高效的空间复杂度:epoll 内核事件表采用红黑树数据结构,对于大量的文件描述符,查找和插入的时间复杂度为 O(log n)。

epoll 的工作原理

epoll 的工作原理可以分为以下几个步骤:

1. 创建 epoll 实例:

#include <sys/epoll.h>int epoll_create(int size);
int epoll_create1(int flags);

通过调用 epoll_create() 函数创建一个 epoll 实例,返回一个文件描述符,即 epoll 文件描述符。

功能: epoll_create 函数和epoll_create1函数用于创建一个 epoll 实例(epoll 文件描述符),以用于 I/O 多路复用。
返回值: 成功时,返回一个非负整数,表示新创建的 epoll 实例的文件描述符。失败时,返回 -1,并设置全局变量 errno 表示具体的错误。
参数说明:
size:这个参数是一个整数提示,用于指定内核应为 epoll 实例分配的事件监视表的大小。然而,自 Linux 2.6.8 版本以来,这个参数被忽略,建议传递任何正数值(例如 1)。
flags:这个参数是一个整数,用于指定创建 epoll 实例的标志。

可以是以下标志之一:
EPOLL_CLOEXEC:为新文件描述符设置 close-on-exec(O_CLOEXEC)标志,表示 epoll 实例在执行 exec 系列函数时将自动关闭。这对于在子进程中避免资源泄漏很有用,例如在 fork 后。

注意: epoll_create1 函数是 epoll 系统调用的较新版本,允许设置 EPOLL_CLOEXEC 标志,以实现更好的资源管理。

#include <sys/epoll.h>int epoll_fd = epoll_create1(0);
if (epoll_fd == -1) {perror("epoll_create");return 1;
}

2.注册文件描述符:

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

功能: epoll_ctl() 函数用于向 epoll 实例注册或修改文件描述符的事件。
返回值: 成功时,返回 0 表示操作成功;失败时,返回 -1,并设置全局变量 errno 表示具体的错误。
参数说明:
epfd:epoll 实例的文件描述符,即通过 epoll_create() 或 epoll_create1() 创建的 epoll 文件描述符。
op:表示要执行的操作类型,可以是以下三种操作之一:

EPOLL_CTL_ADD:向 epoll 实例添加一个文件描述符,并监视指定的事件。
EPOLL_CTL_MOD:修改 epoll 实例中已注册的文件描述符的事件。
EPOLL_CTL_DEL:从 epoll 实例中删除一个文件描述符,不再监视其事件。

fd:要操作的文件描述符,即需要注册、修改或删除的文件描述符。
event:用于指定感兴趣的事件类型和相关数据。

struct epoll_event 结构体包含两个成员:events、data
struct epoll_event {
uint32_t events; /* Epoll events /
epoll_data_t data; /
User data variable */
};
events:表示监视的事件类型,可以是以下事件之一或它们的位或运算结果:

EPOLLIN:表示文件描述符可读。
EPOLLOUT:表示文件描述符可写。
EPOLLRDHUP:表示对端关闭连接或者关闭了写入一半的连接。
EPOLLPRI:表示有紧急数据可读。
EPOLLERR:表示发生错误,如连接错误、重置等。
EPOLLHUP:表示发生挂起事件,如连接挂起、对端关闭连接等。
EPOLLET:启用边缘触发模式,即只通知状态改变的事件。
EPOLLONESHOT:一次性触发模式,即事件触发后只能被触发一次。

data:用于存放用户定义的数据,可以是任意类型的指针,通常用于记录与文件描述符相关的数据。
使用 epoll_ctl() 函数将需要监视的文件描述符注册到 epoll 实例中。可以指定感兴趣的事件类型,例如可读事件、可写事件等。

struct epoll_event ev;
ev.events = EPOLLIN; // 监视可读事件
ev.data.fd = sockfd;if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &ev) == -1) {perror("epoll_ctl");return 1;
}

3.等待事件:

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)

功能: epoll_wait() 函数用于等待 epoll 实例中的文件描述符上的事件发生,并将触发的事件填充到用户提供的数组中。
返回值: 成功时,返回触发事件的文件描述符数量,即填充到 events 数组中的事件数量;失败时,返回 -1,并设置全局变量 errno 表示具体的错误
参数说明:
epfd:epoll 实例的文件描述符,即通过 epoll_create() 或 epoll_create1() 创建的 epoll 文件描述符。
events:用于存放触发的事件的数组结构体地址,函数将把触发的事件填充到该数组中。
maxevents:表示 events 数组的最大容量,即可以存放的最大事件数量。
timeout:指定等待的超时时间(以毫秒为单位)。可以是以下值之一:

-1:表示阻塞等待,直到有事件发生为止。
0:表示立即返回,即非阻塞等待,如果没有事件发生则立即返回,不会等待。
大于0:表示等待指定的毫秒数,如果在指定时间内有事件发生则返回,否则超时返回。

使用 epoll_wait()函数等待事件的发生。当有文件描述符上的事件发生时,epoll_wait() 会返回触发事件的文件描述符信息。

#define MAX_EVENTS 10struct epoll_event events[MAX_EVENTS];while (1) {int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);if (num_events == -1) {perror("epoll_wait");return 1;}// 处理事件for (int i = 0; i < num_events; ++i) {if (events[i].data.fd == sockfd) {// 可读事件发生,进行读取操作// ...}}
}

在以上代码中,我们展示了创建 epoll 实例、将文件描述符注册到 epoll 实例以及等待事件发生的过程。在实际应用中,我们可以根据具体的需求进行相应的操作和处理。这些代码片段可以作为示例帮助理解 epoll 的用法和原理。

总结:
本文介绍了 epoll 这一高效的 Linux I/O 多路复用机制,它可以有效地处理多个并发连接,并避免了传统阻塞式 I/O 的性能和资源问题。通过理解 epoll 的工作原理和用法,我们可以在网络编程中更好地应对高并发的场景,提高程序的性能和扩展性。

相关文章:

网络编程——多路复用——epoll机制

理解 epoll&#xff1a;高效的 Linux I/O 多路复用机制 在网络编程中&#xff0c;处理多个并发连接是一个常见的挑战。传统的方式通常使用阻塞式 I/O 或者多线程/多进程来处理并发连接&#xff0c;但这些方法都存在一些性能和资源管理的问题。为了解决这些问题&#xff0c;Lin…...

chapter14:springboot与安全

Spring Boot与安全视频 Spring Security, shiro等安全框架。主要功能是”认证“和”授权“&#xff0c;或者说是访问控制。 认证&#xff08;Authentication&#xff09;是建立在一个声明主体的过程&#xff08;一个主体一般指用户&#xff0c;设备或一些可以在你的应用程序中…...

Linux初识网络基础

目录 网络发展 认识“协议 ” 网络协议 OSI七层模型&#xff1a; TCP/IP五层&#xff08;或四层&#xff09;模型 网络传输基本流程 网络传输流程图&#xff1a; 数据包封装和封用 网络中的地址 认识IP地址&#xff1a; 认识MAC地址&#xff1a; 网络发展 1.独立…...

vue3+ts 动态导入多文件组件

1、在components文件夹中新建index.ts文件&#xff08;components文件夹下为创建的组件&#xff09; // index.ts const modules import.meta.globEager("./*.vue"); //参数为组件路径 let componentsOpts {}const getCaption (obj, str, z: boolean) > {let…...

补充122836356

ul {margin-bottom: 20px;& > li {margin-bottom: 0;} }等效于ul {margin-bottom: 20px; }ul > li {margin-bottom: 0; }CSS中的&代表的什么 如源码&#xff1a; ul{ margin-bottom: 20px; & >li { margin-bottom: 0; } } & 表示嵌套的上一级 这是s…...

记录 pl-table 表格头部文字抖动的问题

本文记录一个实际开发中 pl-table 的问题&#xff0c;项目比较老&#xff0c;vue还是2.x版本。pl-table 是基于 el-table 改造过来的表格展示组件&#xff0c;已经停止更新。 问题描述 当 data 内数据动态改变时&#xff0c;pl-table 的表头部分&#xff0c;列的文字会左右抖动…...

Vite 创建 Vue项目之后,eslint 错误提示的处理

使用 npm create vuelatest创建 vue 项目&#xff08;TS&#xff09;之后&#xff0c;出现了一些 eslint 错误提示&#xff0c;显然&#xff0c;不是代码真实的错误&#xff0c;而是提示搞错了。 vuejs/create-vue: &#x1f6e0;️ The recommended way to start a Vite-pow…...

FFmpeg 硬编码VideoToolBox流程

介绍 FFmpeg已经提供对 VideoToolBox 的编解码支持&#xff1b;主要涉及到的文件有videotoolbox.c、videotoolbox.h、videotoolboxenc.c、ffmepg_videotoolbox.c。在编译 FFmpeg 源码时&#xff0c;想要支持VideoToolBox&#xff0c;在 configure 时&#xff0c;需要–enable-…...

恒盛策略:内盘是买入还是卖出?

内盘&#xff0c;又称成交明细&#xff0c;是指交易所实时发布的每一笔成交价格、交易时刻、成交量等具体数据。关于股民来说&#xff0c;每天重视内盘数据已成为必修课。可是&#xff0c;当看到内盘数据时&#xff0c;很多人都会困惑&#xff0c;到底内盘是买入还是卖出呢&…...

安装Lombok--Lombok的常用注解说明及使用方法

&#x1f600;前言 本篇博文是关于Lombok的基本介绍和基本使用&#xff0c;希望能够帮助到您&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满…...

无涯教程-Perl - endpwent函数

描述 此功能告诉系统您不再希望使用getpwent从密码文件读取条目。在Windows下,使用Win32API::Net函数从域服务器获取信息。 语法 以下是此函数的简单语法- endpwent返回值 此函数不返回任何值。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perlwhile(($name, $pas…...

vue项目在body设置公共的背景前提下,区分首页背景图和其他页面背景图

1.需求:在vue项目已设置统一的body背景图的前提,单独给首页换一个背景图,然后其他页面背景图不变的临时需求 实现思路1:在首页home.vue中 在公共的style.css文件中写上两个背景样式(写在公共样式中是因为style.css比组件内部的先加载,避免页面出现后背景空白的问题) …...

测试人员该怎样写软件缺陷报告?

软件测试过程中&#xff0c;每个公司都制订了软件的缺陷处理流程&#xff0c;每个公司的软件缺陷处理流程不尽相同&#xff0c;但是它们遵循的最基本流程是一样的&#xff0c;都要经过提交、分配、确认、处理、复测、关闭等环节&#xff0c;如图1所示。 缺陷处理流程 关于图1所…...

【大数据】Flink 详解(二):核心篇 Ⅱ

Flink 详解&#xff08;二&#xff09;&#xff1a;核心篇 Ⅱ 22、刚才提到 State&#xff0c;那你简单说一下什么是 State。 在 Flink 中&#xff0c;状态 被称作 state&#xff0c;是用来保存中间的计算结果或者缓存数据。根据状态是否需要保存中间结果&#xff0c;分为 无状…...

一孩半政策

一&#xff09; 一孩半&#xff0c;又称独女户二胎&#xff0c;即中国大陆部分农村的一项计划生育政策&#xff0c;第一胎是女孩的夫妻可生育第二个子女。试问这个政策会不会影响男女平衡。 二&#xff09;如果生女孩一直生&#xff0c;直到生男孩停止&#xff0c;试问会不会…...

如何在 Spring Boot 中集成日志框架 SLF4J、Log4j

文章目录 具体步骤附录 笔者的操作环境&#xff1a; Spring Cloud Alibaba&#xff1a;2022.0.0.0-RC2 Spring Cloud&#xff1a;2022.0.0 Spring Boot&#xff1a;3.0.2 Nacos 2.2.3 Maven 3.8.3 JDK 17.0.7 IntelliJ IDEA 2022.3.1 (Ultimate Edition) 具体步骤 因为 …...

如何在Linux布置nginx(附带Nginx基本操作步骤)

文章目录 前言一、下载环境依赖二、下载nginx安装包三、具体操作流程总结 前言 提示&#xff1a;下述操作步骤适合内网服务器、局域网服务器和公网服务器。 不足之处欢迎交流指正&#xff0c;不喜勿喷。 一、下载环境依赖 yum -y install gcc zlib zlib-devel pcre-devel ope…...

Xcode升级导致关联库报错

想办法找到对应的库 然后到 Build Phases -- LinkBinary With Libraries中点击&#xff0c;选择对应的framework即可&#xff0c;就像我工程的报错 Undefined symbol: _OBJC_CLASS_$_ADClient _OBJC_CLASS_$_ASIdentifierManager 缺失的库是AdSupport.framework 添加后再次编…...

利用docker run --rm 命令实现使用宿主机中没有的命令

利用docker run --rm 命令实现使用宿主机中没有的命令 使用容器中的jar命令解压jar包&#xff0c;并将解压内容输出到挂载在宿主机中的目录里使用宿主机中没有的nmap命令来通过端口找IP 使用容器中的jar命令解压jar包&#xff0c;并将解压内容输出到挂载在宿主机中的目录里 do…...

中级课程——XSS

文章目录 介绍挖掘思路分类反射型存储型dom类型 介绍 挖掘思路 注入点&#xff1a;各种输入框 测试代码&#xff08;poc&#xff09;&#xff1a;js语句 分类 反射型 存储型 dom类型...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...