IO多路复用实现并发服务器
一.select函数
select 的调用注意事项
在使用 select 函数时,需要注意以下几个关键点:
1. 参数的修改与拷贝
readfds 等参数是结果参数 :
select 函数会直接修改传入的 fd_set(如 readfds、writefds 和 exceptfds)。
为了保留原始监听集合,通常会定义一个备份集合(如 allread_fdset),并将它的拷贝传递给 select。
示例:
fd_set allread_fdset, readfds;
FD_ZERO(&allread_fdset);
FD_SET(fd1, &allread_fdset);
FD_SET(fd2, &allread_fdset);
readfds = allread_fdset; // 拷贝到临时集合
select(..., &readfds, ...);
2. 计算 nfds
nfds 是最大文件描述符值 + 1 :
在新增监听句柄时,更新 nfds 较为简单。
在减少监听句柄时,更新 nfds 较为复杂:
如果需要精确计算,可以通过遍历或维护一个最大堆等数据结构来找到第二大的文件描述符。
或者,可以选择忽略 nfds 的更新,但可能导致性能下降。
3. 超时参数 timeout
timeout 的含义 :
如果为 NULL,表示阻塞等待,直到有事件发生。
如果指向的时间为 0,表示非阻塞模式。
如果指定超时时间,则 select 会在超时后返回。
注意:Linux 实现中,select 返回时会修改 timeout 为剩余时间 :
如果需要重复使用 timeout,需要重新初始化。
4. 返回值的处理
返回值的意义 :
-1:表示错误。
0:表示超时时间到,没有事件发生。
正数:表示监听到的事件总数(包括可读、可写和异常事件)。
优化事件处理 :
可以利用返回值避免不必要的检查。例如,如果返回值为 1,并且已经在可读集合中处理了一个事件,则无需再检查可写和异常集合。
select 的缺点
尽管 select 是一种经典的 I/O 多路复用机制,但它存在以下显著缺点:
1. 文件描述符数量限制
FD_SETSIZE 的限制 :
每个 fd_set 最多只能监听 FD_SETSIZE 个文件描述符(在 Linux 上通常是 1024)。
这一限制使得 select 不适合高并发场景。
2. 遍历效率低
需要逐一检查文件描述符 :
返回的 fd_set 是一个位图,应用程序需要对所有监听的文件描述符逐一调用 FD_ISSET 来判断是否就绪。
示例:
for (int i = 0; i < nfds; i++) {
if (FD_ISSET(i, &readfds)) {
// 处理可读事件
}
}
3. nfds 的效率问题
select 的实现方式 :
select 内部会遍历从 0 到 nfds-1 的所有文件描述符,判断每个描述符是否是关心的,并检查是否有事件发生。
即使只监听少数几个文件描述符(如 0 和 1000),select 仍然需要遍历 1001 个描述符,导致效率低下。
总结
优点
简单易用,跨平台支持广泛。
缺点
文件描述符数量受限 :最多只能监听 FD_SETSIZE 个文件描述符。
遍历效率低 :需要逐一检查文件描述符,增加了开销。
nfds 的问题 :即使监听的文件描述符稀疏分布,select 仍需遍历所有小于 nfds 的描述符。
这些缺点促使了更高效的 I/O 多路复用机制(如 poll 和 epoll)的出现,尤其是在高并发场景下,epoll 成为了更优的选择。
【1】管道select
【2】tcp服务器select
二.poll函数
poll
针对select 做了改进
底层实现 --- 用的是数组
poll --- 链表
poll 引入了事件机制
1. 遍历?
2. poll 需要在 用户空间 和 内核空间 来回拷贝
epoll
三种多路IO操作中最高效
三.epoll函数
3. epoll
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
epoll 解决了select和poll的几个性能上的缺陷:
① 不限制监听的描述符个数(poll也是),只受进程打开描述符总数的限制;
② 监听性能不随着监听描述 符数的增加而增加,是O(1) 的,
不再是轮询描述符来探测事件,而是由描述符主动上报事件; //事件机制的
③ 使用共享内存的方式,不在用户和内核之间反复传递监听的描述 符信息;
④ 返回参数中就是触发事件的列表,不用再遍历输入事件表查询各个事件是否被触发
------------------------------------------
epoll显著提高性能的前提是:
监听大量描述符,
并且每次触发事件的描述符文件非常少。
epoll的另外区别是:
①epoll创建了描述符,记得close;
②支持水平触发和边沿触发。
epoll使用注意事项:
//epoll_create
① int epoll_create(int size); //创建epoll文件描述符
参数size并不是限制了epoll所能监听的描述符最大个数,
只是对内核初始分配内部数据结构的一个建议。
返回是epoll描述符。-1表示创建失败。
//epoll_ctl
② int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); //epoll文件描述符的控制接口
功能:
epoll_ctl控制对指定描述符fd执行op操作,event是与fd关联的监听事件。
参数:
@epfd --- epoll对象
@op
op操作有三种:
添加EPOLL_CTL_ADD,
删除EPOLL_CTL_DEL,
修改EPOLL_CTL_MOD。
分别添加、删除和修改对fd的监听事件。
重复添加fd会怎样(event相同或不相同):
添加失败(errno:17, File exists)
删除和修改不存在的fd会怎样:
删除或修改失败(errno:9,Bad file descriptor)
@fd -- 关心的fd
event是与监听的fd相关联的事件信息,event->events描述了要监听的事件类型,有以下类型:
//事件类型:
EPOLLIN 可读
EPOLLOUT 可写
EPOLLRDHUP 套接口对端close或shutdown写,在ET模式下比较有用
EPOLLPRI 紧急数据可读
EPOLLERR 异常条件
EPOLLHUP 挂起,EPOLLERR和EPOLLHUP始终由epoll_wait监听,不需要用户设置
EPOLLET 边沿触发模式,在描述符状态跳变时才上报监听事件。(监听默认都是LT模式)(ET+非阻塞模式)
EPOLLONESHOT 只一次有效,设置oneshot标记,描述符在触发一次事件之后自动失效(fd还被监听),
不会再上报任何事件,直到使用EPOLL_CTL_MOD重新激活,
设置新的监听事件为止(可不可以和之前的事件一样?)。
event->data是个共用体,可以存放和fd绑定的描述符信息,
比如就存放描述符本身fd,或者一个结构体信息,包括fd,ip,port等等。
在epoll_wait返回时,只会返回一个event列表,需要从列表元素中获取fd等信息。
返回值:
返回0表示控制成功,
返回-1表示失败。
③ int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
//等待epfd上的io事件,最多返回maxevents个事件
timeout = -1 的行为是block;
timeout = 0 是立即返回
④ epoll监听ET事件时,fd必须是非阻塞套接口。
比如监听可读事件,当ET上报可读后,需要一直读fd直到遇到EAGAIN错误为止,以免遗留数据在缓冲区中。
如果fd是阻塞的,则会读到阻塞了。
EAGAIN错误对于非阻塞套接口来说不是错误,只是说没有数据可读或者没有空间可写。
EWOULDBLOCK就是EAGAIN,值都是11。
selset/poll/epoll的LT模式监听的fd可以是阻塞模式的。
⑤ 多路复用监听io事件时,如果对某个套接口监听可写事件,总是会返回可写而事实上可能没有数据要写。
处理方法:
①只有在有数据要写时才把要写的套接口加入 监听列表中,数据全部写完之后从监听列表中删除它;
②在有数据写时,首先尝试直接写,当直接写没有把数据全部写入发送缓冲区时再把这个套接口加入可写事件 监听列表。
(这种方式效率较高,需要套接口是非阻塞的,前一种方式可以是阻塞的吗?)
可以是阻塞的。
四. 特点和区别
相关文章:

IO多路复用实现并发服务器
一.select函数 select 的调用注意事项 在使用 select 函数时,需要注意以下几个关键点: 1. 参数的修改与拷贝 readfds 等参数是结果参数 : select 函数会直接修改传入的 fd_set(如 readfds、writefds 和 exceptfds…...
【漫话机器学习系列】122.相关系数(Correlation Coefficient)
深入理解相关系数(Correlation Coefficient) 1. 引言 在数据分析、统计学和机器学习领域,研究变量之间的关系是至关重要的任务。我们常常想知道:当一个变量变化时,另一个变量是否也会随之变化?如果会&…...
控制系统分类
文章目录 定义与特点1. 自治系统(Autonomous System)与非自治系统(Non-Autonomous System)自治系统非自治系统 2. 线性系统(Linear System)与非线性系统(Nonlinear System)线性系统非…...

文档操作方法得合理使用
博主介绍:✌全网粉丝5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…...
Python asyncIO 面试题及参考答案 草
目录 如何正确定义一个协程函数?直接调用协程会引发什么问题? 使用 async def 定义的协程与普通函数执行流程有何本质区别? 解释 asyncio.run () 的作用及与手动管理事件循环的差异 为什么协程中必须使用 await 而非 yield 挂起操作? 写出通过 async for 实现异步迭代器…...

计算机网络——交换机
一、什么是交换机? 交换机(Switch)是局域网(LAN)中的核心设备,负责在 数据链路层(OSI第二层)高效转发数据帧。它像一位“智能交通警察”,根据设备的 MAC地址 精准引导数…...

matlab和FPGA联合仿真时读写.txt文件数据的方法
在FPGA开发过程中,往往需要将MATLAB生成的数据作为原始激励灌入FPGA进行仿真。为了验证FPGA计算是否正确,又需要将FPGA计算结果导入MATLAB绘图与MATLAB计算结果对比。 下面是MATLAB“写.txt”、“读.txt”,Verilog“读.txt”、“写.txt”的代…...

解锁DeepSpeek-R1大模型微调:从训练到部署,打造定制化AI会话系统
目录 1. 前言 2.大模型微调概念简述 2.1. 按学习范式分类 2.2. 按参数更新范围分类 2.3. 大模型微调框架简介 3. DeepSpeek R1大模型微调实战 3.1.LLaMA-Factory基础环境安装 3.1大模型下载 3.2. 大模型训练 3.3. 大模型部署 3.4. 微调大模型融合基于SpirngBootVue2…...

【分布式】聊聊分布式id实现方案和生产经验
对于分布式Id来说,在面试过程中也是高频面试题,所以主要针对分布式id实现方案进行详细分析下。 应用场景 对于无论是单机还是分布式系统来说,对于很多场景需要全局唯一ID, 数据库id唯一性日志traceId 可以方便找到日志链&#…...

uniapp或者vue 使用serialport
参考https://blog.csdn.net/ykee126/article/details/90440499 版本是第一位:否则容易编译失败 node 版本 18.14.0 npm 版本 9.3.1 electron 版本 30.0.8 electron-rebuild 版本 3.2.9 serialport 版本 10.0.0 需要python环境 main.js // Modules to control app…...

机器学习12-视觉识别任务
机器学习12-视觉识别任务 分类语义分割滑动窗口滑动窗口的实现思路优点缺点现代替代方法 全卷积(Fully Convolutional Networks, FCN)FCN 的工作原理FCN 的性能优势FCN 的应用案例FCN 的局限性改进方向下采样可学习的上采样:转置卷积 目标检测区域建议Se…...

使用paramiko爆破ssh登录
一.确认是否存在目标主机是否存在root用户 重跑 CVE-2018-15473用户名枚举漏洞 检测: import paramiko from paramiko.ssh_exception import AuthenticationExceptiondef check_user(username, hostname, port):ssh paramiko.SSHClient()ssh.set_missing_host_key…...

游戏引擎学习第146天
音高变化使得对齐读取变得不可能,我们可以支持循环声音了。 我们今天的目标是完成之前一段时间所做的音频代码。这个项目并不依赖任何引擎或库,而是一个教育项目,目的是展示从头到尾运行一个游戏所需要的全部代码。无论你对什么方面感兴趣&a…...

装饰器模式--RequestWrapper、请求流request无法被重复读取
目录 前言一、场景二、原因分析三、解决四、更多 前言 曾经遇见这么一段代码,能看出来是把request又重新包装了一下,核心信息都不会改变 后面了解到这叫 装饰器模式(Decorator Pattern) :也称为包装模式(Wrapper Pat…...

【算法题】小鱼的航程
问题: 分析 分析题目,可以看出,给你一个开始的星期,再给一个总共天数,在这些天内,只有周六周日休息,其他全要游泳250公里。 那分支处理好啦 当星期为6时,需要消耗2天,…...

视频录像机视频通道是指什么
视频录像机的视频通道是指摄像机在监控矩阵或硬盘录像机设备上的视频输入的物理位置。 与摄像头数量关系:在视频监控系统中,有多少个摄像头就需要多少路视频通道,通道数量决定了视频录像机可接入摄像头的数量,一般硬盘录像机有4路…...

RISC-V医疗芯片工程师复合型转型的路径与策略
从RISC-V到医疗芯片:工程师复合型转型的路径与策略 一、引言 1.1 研究背景 在科技快速发展的当下,芯片技术已然成为推动各行业进步的核心驱动力之一。其中,RISC-V 架构作为芯片领域的新兴力量,正以其独特的优势迅速崛起,对整个芯片产业的格局产生着深远影响。RISC-V 架…...
《Gradio : AI awesome-demos》
《Gradio : AI awesome-demos》 This is a list of some wonderful demos & applications built with Gradio. Heres how to contribute yours! 🖊️ Natural language processing Demo name (link to demo)input type(s)output type(s)status badgeruDALL-ET…...

DeepSeek R1-7B 医疗大模型微调实战全流程分析(全码版)
DeepSeek R1-7B 医疗大模型微调实战全流程指南 目录 环境配置与硬件优化医疗数据工程微调策略详解训练监控与评估模型部署与安全持续优化与迭代多模态扩展伦理与合规体系故障排除与调试行业应用案例进阶调优技巧版本管理与迭代法律风险规避成本控制方案文档与知识传承1. 环境配…...

javascript实现生肖查询
今年是农历乙巳年,蛇年,今天突发奇想,想知道公元0年是农历什么年,生肖是什么。没想到AI给我的答复是,没有公元0年。我瞬间呆愣,怎么可能?后来详细查询了一下,还真是没有。具体解释如…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...

CTF show 数学不及格
拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 用IDA Pro 64 打开这个文件 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 根据题目…...

Java设计模式:责任链模式
一、什么是责任链模式? 责任链模式(Chain of Responsibility Pattern) 是一种 行为型设计模式,它通过将请求沿着一条处理链传递,直到某个对象处理它为止。这种模式的核心思想是 解耦请求的发送者和接收者,…...