网络编程——多路复用——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 具有以下优势:
- 高效:epoll 使用了更加高效的数据结构和算法,能够在大规模并发连接下提供更好的性能。
- 扩展性:epoll 支持水平触发和边缘触发两种模式,可以根据应用的需求选择不同的触发模式。
- 节省资源:epoll 使用一个文件描述符来管理多个连接,而不是每个连接都需要一个文件描述符,从而节省了资源。
- 没有连接数限制:epoll 没有连接数的限制,可以处理成千上万个并发连接。
- 高效的空间复杂度: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:高效的 Linux I/O 多路复用机制 在网络编程中,处理多个并发连接是一个常见的挑战。传统的方式通常使用阻塞式 I/O 或者多线程/多进程来处理并发连接,但这些方法都存在一些性能和资源管理的问题。为了解决这些问题,Lin…...
chapter14:springboot与安全
Spring Boot与安全视频 Spring Security, shiro等安全框架。主要功能是”认证“和”授权“,或者说是访问控制。 认证(Authentication)是建立在一个声明主体的过程(一个主体一般指用户,设备或一些可以在你的应用程序中…...
Linux初识网络基础
目录 网络发展 认识“协议 ” 网络协议 OSI七层模型: TCP/IP五层(或四层)模型 网络传输基本流程 网络传输流程图: 数据包封装和封用 网络中的地址 认识IP地址: 认识MAC地址: 网络发展 1.独立…...
vue3+ts 动态导入多文件组件
1、在components文件夹中新建index.ts文件(components文件夹下为创建的组件) // 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中的&代表的什么 如源码: ul{ margin-bottom: 20px; & >li { margin-bottom: 0; } } & 表示嵌套的上一级 这是s…...
记录 pl-table 表格头部文字抖动的问题
本文记录一个实际开发中 pl-table 的问题,项目比较老,vue还是2.x版本。pl-table 是基于 el-table 改造过来的表格展示组件,已经停止更新。 问题描述 当 data 内数据动态改变时,pl-table 的表头部分,列的文字会左右抖动…...
Vite 创建 Vue项目之后,eslint 错误提示的处理
使用 npm create vuelatest创建 vue 项目(TS)之后,出现了一些 eslint 错误提示,显然,不是代码真实的错误,而是提示搞错了。 vuejs/create-vue: 🛠️ The recommended way to start a Vite-pow…...
FFmpeg 硬编码VideoToolBox流程
介绍 FFmpeg已经提供对 VideoToolBox 的编解码支持;主要涉及到的文件有videotoolbox.c、videotoolbox.h、videotoolboxenc.c、ffmepg_videotoolbox.c。在编译 FFmpeg 源码时,想要支持VideoToolBox,在 configure 时,需要–enable-…...
恒盛策略:内盘是买入还是卖出?
内盘,又称成交明细,是指交易所实时发布的每一笔成交价格、交易时刻、成交量等具体数据。关于股民来说,每天重视内盘数据已成为必修课。可是,当看到内盘数据时,很多人都会困惑,到底内盘是买入还是卖出呢&…...
安装Lombok--Lombok的常用注解说明及使用方法
😀前言 本篇博文是关于Lombok的基本介绍和基本使用,希望能够帮助到您😊 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满…...
无涯教程-Perl - endpwent函数
描述 此功能告诉系统您不再希望使用getpwent从密码文件读取条目。在Windows下,使用Win32API::Net函数从域服务器获取信息。 语法 以下是此函数的简单语法- endpwent返回值 此函数不返回任何值。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perlwhile(($name, $pas…...
vue项目在body设置公共的背景前提下,区分首页背景图和其他页面背景图
1.需求:在vue项目已设置统一的body背景图的前提,单独给首页换一个背景图,然后其他页面背景图不变的临时需求 实现思路1:在首页home.vue中 在公共的style.css文件中写上两个背景样式(写在公共样式中是因为style.css比组件内部的先加载,避免页面出现后背景空白的问题) …...
测试人员该怎样写软件缺陷报告?
软件测试过程中,每个公司都制订了软件的缺陷处理流程,每个公司的软件缺陷处理流程不尽相同,但是它们遵循的最基本流程是一样的,都要经过提交、分配、确认、处理、复测、关闭等环节,如图1所示。 缺陷处理流程 关于图1所…...
【大数据】Flink 详解(二):核心篇 Ⅱ
Flink 详解(二):核心篇 Ⅱ 22、刚才提到 State,那你简单说一下什么是 State。 在 Flink 中,状态 被称作 state,是用来保存中间的计算结果或者缓存数据。根据状态是否需要保存中间结果,分为 无状…...
一孩半政策
一) 一孩半,又称独女户二胎,即中国大陆部分农村的一项计划生育政策,第一胎是女孩的夫妻可生育第二个子女。试问这个政策会不会影响男女平衡。 二)如果生女孩一直生,直到生男孩停止,试问会不会…...
如何在 Spring Boot 中集成日志框架 SLF4J、Log4j
文章目录 具体步骤附录 笔者的操作环境: Spring Cloud Alibaba:2022.0.0.0-RC2 Spring Cloud:2022.0.0 Spring Boot: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安装包三、具体操作流程总结 前言 提示:下述操作步骤适合内网服务器、局域网服务器和公网服务器。 不足之处欢迎交流指正,不喜勿喷。 一、下载环境依赖 yum -y install gcc zlib zlib-devel pcre-devel ope…...
Xcode升级导致关联库报错
想办法找到对应的库 然后到 Build Phases -- LinkBinary With Libraries中点击,选择对应的framework即可,就像我工程的报错 Undefined symbol: _OBJC_CLASS_$_ADClient _OBJC_CLASS_$_ASIdentifierManager 缺失的库是AdSupport.framework 添加后再次编…...
利用docker run --rm 命令实现使用宿主机中没有的命令
利用docker run --rm 命令实现使用宿主机中没有的命令 使用容器中的jar命令解压jar包,并将解压内容输出到挂载在宿主机中的目录里使用宿主机中没有的nmap命令来通过端口找IP 使用容器中的jar命令解压jar包,并将解压内容输出到挂载在宿主机中的目录里 do…...
中级课程——XSS
文章目录 介绍挖掘思路分类反射型存储型dom类型 介绍 挖掘思路 注入点:各种输入框 测试代码(poc):js语句 分类 反射型 存储型 dom类型...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
