当前位置: 首页 > 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类型...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...