Linux 中 epoll 的详解
Linux 中 epoll 的详解
epoll 是 Linux 内核提供的一种高效的 I/O 多路复用机制,用于监控大量文件描述符的 I/O 事件。相较于传统的 select 和 poll,epoll 在高并发和大规模网络编程场景下表现出色,特别适合需要处理成千上万个文件描述符的应用。
1. epoll 的特点
优点
-
高效性:
- 内核采用事件驱动机制,只在有事件时通知程序,而不是轮询所有文件描述符。
- 避免了重复构造文件描述符集合的开销。
-
无文件描述符上限:
- 文件描述符数量仅受系统资源限制,而不像
select的FD_SETSIZE限制(默认 1024)。
- 文件描述符数量仅受系统资源限制,而不像
-
支持边缘触发(ET)和水平触发(LT):
- ET:仅在状态变化时触发通知。
- LT:只要状态未清除,就会持续触发通知。
-
内存拷贝优化:
- 用户态和内核态之间的交互效率更高。
缺点
- 仅支持 Linux 系统,跨平台性较差。
- 边缘触发(ET)模式需要额外的逻辑处理,编程复杂度较高。
2. epoll 的使用方法
epoll 的使用主要分为三步:
1. 创建 epoll 实例
使用 epoll_create1 或 epoll_create 创建一个 epoll 实例:
#include <sys/epoll.h>int epoll_create1(int flags);
int epoll_create(int size);
flags:设置为 0 或EPOLL_CLOEXEC(子进程不继承)。- 返回值:一个文件描述符,用于管理
epoll实例。
2. 注册和管理文件描述符
使用 epoll_ctl 添加、修改或删除监控的文件描述符:
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epfd:epoll_create返回的文件描述符。op:操作类型(EPOLL_CTL_ADD、EPOLL_CTL_MOD、EPOLL_CTL_DEL)。fd:需要监控的文件描述符。event:事件结构体,定义了监控的事件类型和用户数据。
struct epoll_event {uint32_t events; /* 事件类型 */epoll_data_t data; /* 用户数据 */
};typedef union epoll_data {void *ptr;int fd;uint32_t u32;uint64_t u64;
} epoll_data_t;
events常见值:EPOLLIN:可读事件。EPOLLOUT:可写事件。EPOLLERR:错误事件。EPOLLET:边缘触发模式。EPOLLHUP:挂起事件。
3. 等待事件发生
使用 epoll_wait 阻塞等待事件:
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
epfd:epoll_create返回的文件描述符。events:用于存储触发的事件。maxevents:events数组的最大长度。timeout:超时时间(毫秒)。0:立即返回。-1:无限等待。
返回值:发生事件的文件描述符数量。
3. epoll 使用示例
示例:基本用法
以下代码展示如何使用 epoll 同时监控标准输入和一个文件描述符:
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>int main() {int epfd = epoll_create1(0); // 创建 epoll 实例if (epfd == -1) {perror("epoll_create1");exit(EXIT_FAILURE);}struct epoll_event ev, events[10];ev.events = EPOLLIN; // 监控可读事件ev.data.fd = STDIN_FILENO; // 标准输入if (epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1) {perror("epoll_ctl");exit(EXIT_FAILURE);}printf("等待输入...\n");while (1) {int nfds = epoll_wait(epfd, events, 10, -1); // 无限等待if (nfds == -1) {perror("epoll_wait");exit(EXIT_FAILURE);}for (int i = 0; i < nfds; ++i) {if (events[i].data.fd == STDIN_FILENO) {char buffer[1024];int len = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);if (len > 0) {buffer[len] = '\0';printf("输入内容:%s\n", buffer);}}}}close(epfd);return 0;
}
4. epoll 的触发模式
水平触发(LT:Level Triggered)
- 默认模式。
- 如果文件描述符状态未清除,每次调用
epoll_wait都会触发事件。 - 容易实现,但性能稍低。
示例:
while (1) {int nfds = epoll_wait(epfd, events, 10, -1);for (int i = 0; i < nfds; ++i) {if (events[i].events & EPOLLIN) {read(fd, buffer, sizeof(buffer)); // 处理事件}}
}
边缘触发(ET:Edge Triggered)
- 高性能模式。
- 文件描述符状态发生变化时仅触发一次,必须读取或写入所有数据。
- 如果未处理完毕,可能会丢失事件。
实现注意:
- 必须使用非阻塞文件描述符。
- 需要循环读取或写入直到完成。
示例:
while (1) {int nfds = epoll_wait(epfd, events, 10, -1);for (int i = 0; i < nfds; ++i) {if (events[i].events & EPOLLIN) {while (1) {int len = read(fd, buffer, sizeof(buffer));if (len == -1) {if (errno == EAGAIN) break; // 无更多数据perror("read");} else if (len == 0) {break; // EOF} else {// 处理数据}}}}
}
5. epoll 的优缺点总结
优点
- 高性能:
- 基于事件通知机制,不需要线性扫描文件描述符集合。
- 灵活性:
- 支持边缘触发(ET)模式,减少不必要的系统调用。
- 无文件描述符限制:
- 能处理大量并发连接,适用于高并发服务器。
缺点
- 复杂性高:
- 编程复杂,特别是边缘触发模式需要处理更多细节。
- 仅适用于 Linux:
- 不支持其他平台,跨平台性较差。
6. epoll 应用场景
- 高并发服务器:
- 如 HTTP 服务器、代理服务器。
- 实时系统:
- 需要快速响应大量 I/O 事件。
- 高性能应用:
- 网络爬虫、流媒体服务器等。
相关文章:
Linux 中 epoll 的详解
Linux 中 epoll 的详解 epoll 是 Linux 内核提供的一种高效的 I/O 多路复用机制,用于监控大量文件描述符的 I/O 事件。相较于传统的 select 和 poll,epoll 在高并发和大规模网络编程场景下表现出色,特别适合需要处理成千上万个文件描述符的应…...
增加nginx配置文件(conf.d), 管理多个项目
1.切换到nginx目录下, 新建conf.d文件夹 mkdir conf.d 2.赋予conf.d权限 chmod 777 conf.d 3.进入conf.d, 编辑conf文件 vim zc_travel.conf server { listen 13101; server_name localhost;location / {root /home/baoxin/app/web/insight-radar-rcfx-pre/html_dev;index …...
PostgreSQL编译安装教程
下载安装 1.在家目录创建一个文件夹放下载安装包 mkdir softwarecd software 2.下载文件压缩包 wget https://ftp.postgresql.org/pub/source/v16.0/postgresql-16.0.tar.gz 3.解压 tar -xzvf postgresql-16.0.tar.gz 4.编译 在software/postgresql-16.0下 cd software…...
【提审】Android包提审报权限问题
问题:华为应用市场审核不通过 平台审核检测详情: 日志: 自检工具:frida-server【Unity&Android】安卓app自测应用隐私相关获取和申请权限_apk 隐私合规 自测-CSDN博客 参考资料:Unity启动时获取了android_id等设…...
xdoj 数字个数统计
1-2 数字个数统计 2 时间限制: 1S 题目描述: 一个正整数 n(1<n<1000),在区间[n,n2 ](含端点)内统计奇数个数、 偶数个数、能被 4 整除且不能被 3 整除的数字个数,并求出各统计数字两两…...
空天地遥感数据识别与计算--数据分析如何助力农林牧渔、城市发展、地质灾害监测等行业革新
在科技飞速发展的时代,遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究,空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而,对于许多专业人士而言,如何高效地处…...
Git:查看分支、创建分支、合并分支
一、查看分支 查看的git命令如下: git branch # 列出本地已经存在的分支,并且当前分支会用*标记 git branch -r # 查看远程版本库的分支列表 git branch -a # 查看所有分支列表(包括本地和远程,remotes/开头的表示远程分支&…...
联合目标检测与图像分类提升数据不平衡场景下的准确率
联合目标检测与图像分类提升数据不平衡场景下的准确率 在一些数据不平衡的场景下,使用单一的目标检测模型很难达到99%的准确率。为了优化这一问题,适当将其拆解为目标检测模型和图像分类模型的组合,可以更有效地控制最终效果,尤其…...
Git的简介
文章目录 一.Git是什么二.核心概念三.工作流程四.Git的优势 下载Git 推荐官网下载 官网地址 一.Git是什么 Git是一个分布式版本控制系统,用于跟踪文件的变化并协调多人对同一项目的开发工作。它就像是一个时光机器,能够记录文件在不同时间点的状态&…...
麒麟操作系统服务架构保姆级教程(四)NGINX中间件
如果你想拥有你从未拥有过的东西,那么你必须去做你从未做过的事情 想要在网页上访问到代码那么就需要用到应用服务类中间件,国外的有Nginx,Tomcat等,国内的有金蝶web,东方通的服务中间件(Tongweb࿰…...
Glide 自定义圆角、铺满FitXY
在 Android 开发中,使用 Glide 来加载图片时,有时需要对图片进行特定的处理,比如设置圆角或者使图片完全填充到一个视图中(类似于 ImageView 的 scaleType 中的 FitXY)。以下是如何使用 Glide 来实现这些自定义需求的处…...
蓝牙协议——音乐启停控制
手机播放音乐 手机暂停音乐 耳机播放音乐 耳机暂停音乐...
Krita安装krita-ai-diffusion工具搭建comfyui报错没有ComfyUI_IPAdapter_plus解决办法
我们在使用Kirta安装krita-ai-diffusion工具之后搭建comfyui环境需要安装很多扩展文件。 一般正常安装都可以使用了。 但是有一个插件很特别,无论你安装多少遍都会显示缺失,是什么插件这么难搞定呢? 没错,就是我们的ComfyUI_IPAdapter_plus插件。 就像下图一样: 那么怎…...
四相机设计实现全向视觉感知的开源空中机器人无人机
开源空中机器人 基于深度学习的OmniNxt全向视觉算法OAK-4p-New 全景硬件同步相机 机器人的纯视觉避障定位建图一直是个难题: 系统实现复杂 纯视觉稳定性不高 很难选到实用的视觉传感器 为此多数厂家还是采用激光雷达的定位方案。 OAK-4p-New 为了弥合这一差距…...
LightGBM分类算法在医疗数据挖掘中的深度探索与应用创新(上)
一、引言 1.1 医疗数据挖掘的重要性与挑战 在当今数字化医疗时代,医疗数据呈爆炸式增长,这些数据蕴含着丰富的信息,对医疗决策具有极为重要的意义。通过对医疗数据的深入挖掘,可以发现潜在的疾病模式、治疗效果关联以及患者的健康风险因素,从而为精准医疗、个性化治疗方…...
JVM(Java虚拟机)的组成部分详解
摘要: JVM (Java Virtual Machine) 是一个抽象计算模型,它使Java程序可以在任何支持JVM的操作系统上运行,而无需考虑底层硬件架构。本文将深入探讨JVM的内部结构和工作机制,包括类加载器、运行时数据区、执行引擎以及内存管理等关…...
jsp中的四个域对象(Spring MVC)
在Spring MVC中,Model中的数据会被自动放入到请求域(Request Scope)中。也就是说,当我们在控制器中使用model.addAttribute()时,这些属性会被放入到HttpServletRequest对象的属性中。 让我们通过代码来详细解释&#…...
计算机基础知识复习12.24
http和https有那些区别 http是超文本传输协议,信息是明文传输,存在安全风险的问题,https则解决http不安全的缺点,在TCP和HTTP网络层之间加入了SSL/TLS安全协议,使得报文能够加密传输 http连接建立相对简单࿰…...
如何使用vscode解决git冲突
在使用VSCode时,遇到Git冲突是很常见的情况。Git冲突是指当多个人同时修改同一个文件的同一行或相邻行时,Git无法自动决定应该保留哪一个修改,需要手动解决这个冲突。 要解决Git冲突,可以按照以下步骤操作: 1. 打开V…...
告别卡顿:CasaOS轻NAS设备安装Gopeed打造高效下载环境
文章目录 前言1. 更新应用中心2.Gopeed安装与配置3. 本地下载测试4. 安装内网穿透工具5. 配置公网地址6. 配置固定公网地址 前言 无论你是需要大量文件传输的专业人士,还是只是想快速下载电影或音乐的普通用户,都会使用到下载工具。如果你对现有的下载工…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
