Linux下的5种I/O模型与3组I/O复用

Linux 网络 I/O 模型简介(图文) 1、介绍 Linux 的内核将所有外部设备都看做一个文件来操作(一切皆文件),对一个文件的读写操作会调用内核提供的系统命令,返回一个file descriptor(fd,文件描述符)。而对一个socket的读写也会有响应的描述符,称为socket fd(socket文件描述符),描述符就是一个数字,指向内核中的一个结构体(文件路径,数据区等一些属性)。 根据UNIX网络编程对I/O模型的分类,UNIX提供了5种I/O模型。 1.1、阻塞I/O模型 最常用的I/O模型,默认 阅读详情

Python微信订餐小程序课程视频

https://edu.youkuaiyun.com/course/detail/36074

Python实战量化交易理财系统

https://edu.youkuaiyun.com/course/detail/35475

引言

上一篇文章中介绍了一些无缓冲文件I/O函数,但应该什么时机调用这些函数,调用这些I/O函数时进程和内核的行为如何,如何高效率地实现I/O?这篇文章就来谈一谈Linux下的5种I/O模型,以及高性能服务器编程中常用的I/O复用,为后面实现精简版本的高性能服务器做铺垫。

Linux下的5种I/O模型

Linux下可用的5种I/O模型:

  • 阻塞I/O
  • 非阻塞I/O
  • I/O复用
  • 信号驱动式I/O
  • 异步I/O

一个输入操作通常包括两个不同阶段:

  1. 等待数据准备好
  2. 从内核向进程复制数据

对于套接字的输入操作来说,第一步是等待数据从网络中到达,当分组到达时,它被暂存到内核的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。

阻塞式I/O

默认情况下,所有套接字都是阻塞的。

阻塞I/O的典型情形如下:

image-20220203153948017
进程对TCP套接字调用read,系统调用直到数据报到达并被复制到应用进程的缓冲区或发生错误才返回。其中等待数据的时间是不可控的,取决于网络何时有数据到来。而对于期间可能发生的错误,最常见的就是被信号中断。

这样的I/O就是阻塞式I/O。

非阻塞I/O

当进程把某个文件描述符设置为非阻塞时,典型的情形如下所示:

image-20220203155600033
对设置为非阻塞的文件描述符调用recvfrom,若没有数据准备好,recvfrom立即返回错误(错误号为EWOULDBLOCK)(调用真的出错时也会立即返回,需要根据errno来区分,常见的因非阻塞事件未发生时的errno为EAGAIN、EWOULDBLOCK、EINPROGRESS)。

若数据准备好,则需要等待内核把数据从内核缓冲区拷贝到进程空间缓冲区。

I/O复用

典型的I/O复用模型如下:

image-20220203160504612
有了I/O复用,我们可以阻塞在I/O复用函数上(select、poll、epoll),等待多个文件就绪,而不用阻塞于对单个文件描述符读写的系统调用。使用select的优势在于可以等待多个描述符就绪。

信号驱动I/O

典型的信号驱动I/O模型如下:

image-20220203160440039
首先开启套接字的信号驱动I/O功能,并安装信号处理函数,进程接下来继续做其他工作,没有被阻塞

当数据报准备好时,内核就为进程产生SIGIO信号,调用前面安装的信号处理函数,在处理函数中调用recvfrom。

优势在于等待数据报到达期间进程无需阻塞。

异步I/O

异步I/O模型如下:

image-20220203160900493
在异步I/O中,调用aio_read将描述符、进程缓冲区指针、进程缓冲区大小、文件偏移告知内核,并告诉内核当操作完成时如何通知我们。该系统调用立即返回,在等待I/O期间进程不被阻塞。

5种I/O模型比较

仔细分析就会发现,虽然有些I/O模型可以不必等待数据就绪(不必阻塞于数据在内核缓冲区准备好的这段时间),但除了异步I/O外,其余4种I/O都无法避免进程阻塞于数据从内核复制到进程空间的这部分时间。

因此,前4种I/O都属于同步式I/O,只有异步I/O模型与POSIX定义的异步I/O匹配。异步I/O将数据从内核复制到用户空间这一任务完全托付给内核处理,不必由进程实时监管,进程只需要给出一些必要信息即可(学过操作系统的同学很快就会发现这有点类似于通过通道处理机在设备和内存之间传送数据)。

下图是这5种I/O模型的时序比较,帮助大家更好理解他们之间的差别:

image-20220203162319638

I/O复用

Linux提供了三个系统调用以支持I/O复用:

  • select
  • poll
  • epoll_wait

我们可以用这些系统调用同时等待多个描述符上的事件就绪。I/O复用函数本身是阻塞的,他们能提高效率的原因就在于具有同时监听多个I/O事件的能力。

select调用

select函数的定义如下:

#include 
#include 
int select(int maxfdp1, fd\_set* read\_set, fd\_set* write\_set, fd\_set* except\_set, const struct timeval* 
 timeout);
返回值:
 有就绪描述符时返回就绪的描述符的数目,超时则返回0,出错返回-1.

参数说明

timeout参数指定select函数最多等待多长时间,如果这段事件内没有就绪描述符,就返回0。timeval结构体定义如下:

struct timeval{
 long tv\_sec;
 long tv\_usec;
};

timeout的3种情形:

  • timeout参数可以为NULL,代表select将永远阻塞直到有描述符就绪。
  • timeout参数不为NULL,且timeval各字段不为0。
  • timeout参数不为NULL,但timeval各字段为0。

select在阻塞期间会被进程在等待期间捕获的信号中断,并从信号处理函数返回,那么select就会返回EINTR的错误。

read_set、write_set、except_set分别指定等待可读、可写、异常(异常条件目前只需关注套接字存在带外数据时的情况)发生的文件描述符集。

fd_set的设定要通过宏来操作:

void FD\_ZERO(fd\_set* fdset); // 清空,fd\_set变量使用前必须要清空
void FD\_SET(int fd, fd\_set* fdset); // 设置某描述符
void FD\_CLR(int fd, fd\_set* fdset); // 取消设置某描述符
int FD\_ISSET(int fd, fd\_set* fdset); // 检查是否设置

maxfdp1参数为等待的所有描述符的最大值加1。

select返回时,会修改fd_set,将未就绪的置为0,就绪的保持。因此中间三个参数为传入传出参数。而且,我们必须通过FD_ISSET宏遍历fd_set,来检查哪些描述符就绪,每次重新调用select时,我们还必须重新设置要等待的描述符集合fd_set。

当某个套接字发生错误时,由select标记为既可读又可写。此处的错误不是excep_set等待的异常条件。

局限

通过上面的介绍可以发现,select返回时我们需要轮询以获取就绪的描述符,效率不高,而且每次调用select必须重新设置fd_set。

此外,select能监听的最大描述符数目是有限制的。

poll调用

poll函数的定义如下:

#include 
int poll(strcut pollfd* fd\_array, unsigned long nfds, int timeout);

返回值:
 若有就绪返回就绪描述符数目;
 超时返回0;
 出错返回-1。

参数说明

struct pollfd定义如下:

struct pollfd{
 int fd;
 short events;
 short revents;
};

要测试的条件由events指定,返回时revents存储就绪事件。

timeout参数指定等待的毫秒数。可以为INFTIM、0、正数。

局限

虽然poll没有了监听描述符数目的限制,但poll返回时我们还是要轮询遍历pollfd,来检查就绪的描述符,同样效率不高。

epoll调用

不同于select、poll,epoll把用户关心的文件描述符上的事件放在内核的一个事件表中,因此无需每次调用都重复传入文件描述符集或事件集。epoll需要使用一个额外的文件描述符,来标识内核中的这个事件表。

创建事件表的函数epoll_create函数定义如下:

#include 
int epoll\_create(int size);

返回:
 成功返回表示事件表的描述符。

size参数只是给内核一个提示,告诉内核事件表需要多大。

操作事件表的函数如下:

#include 
int epoll\_ctl(int epfd, int op, struct epoll\_event* event);

返回值:
 成功返回0;
 失败返回-1。

epfd为epoll_create的返回值。

op指定操作类型,可以为:

  • EPOLL_CTL_ADD:注册fd上的事件。
  • EPOLL_CTL_MOD:修改fd上的注册事件。
  • EPOLL_CTL_DEL:删除fd上的注册事件。

event指定事件和描述符,struct epoll_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;

发起等待的epoll_wait函数定义如下:

#include 
int epoll\_wait(int epfd, struct epoll\_event* events, int maxevents, int timeout);

返回值:
 成功返回就绪的描述符的个数;
 失败返回-1。

events为传出参数,结合maxevents说明了预先开辟的数组空间用于存放就绪的epoll_event。timeout参数与poll接口的timeout相同。

epoll_wait函数如果检测到事件,就将所有就绪的事件从内核事件表中复制到events指向的数组中,这个参数只为传出参数,不像select、poll参数既传入又传出需要轮询,提高了效率。

3种调用的区别

对于3种调用的详细区别以及他们的具体使用例子不可能在本篇文章的篇幅中展开,以后的文章具体分析,这里贴出《Linux高性能服务器编程》一书上的图例:

image-20220203174253833

参考资料

《UNP 卷1》 3/e
《Linux高性能服务器编程》
《后台开发 核心技术与应用实践》

__EOF__

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOTYxTMJ-1643926609598)(https://blog.youkuaiyun.com/hickey2048/p/15861770.html)]Hickey Zhang 本文链接:https://blog.youkuaiyun.com/hickey2048/p/15861770.html关于博主:评论和私信会在第一时间回复。或者直接私信我。版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!声援博主:如果您觉得文章对您有帮助,可以点击文章右下角**【[推荐](javascript:void(0)😉】**一下。您的鼓励是博主的最大动力!

Linux中五种I/O模式 《Linux网络编程》五种I/O模式1、阻塞 I/O2、非阻塞 I/O3、I/O 多路复用4、信号驱动 I/O( SIGIO)5、异步 I/O一般来说,程序进行输入操作有两步:1.等待有数据可以读2.将数据从系统内核中拷贝到程序的数据区。对于一个对套接字的输入操作,第一步一般来说是等待数据从网络上传到本地。当数据包到达的时候,数据将会从网络层拷贝到内核的缓存中;第二步是从内核中把数据拷贝到程序的数... 阅读详情

相关推荐

瑞萨RZN2L工业以太网开发避坑指南:EtherCAT从入门到通信调试全流程

本文详细解析了瑞萨RZN2L MPU在工业以太网开发中的EtherCAT从站配置与通信优化全流程。通过硬件设计关键点、协议栈选型、PDO映射策略及DC同步精度优化等实战技巧,帮助开发者快速搭建高效通信框架并解决调试中的常见问题,特别适合工业自动化领域的实时通信需求。

aitie1479的博客 461

linux常见的I/O复用技术汇总-select、poll、epoll

常见的I/O复用技术详解

深耕嵌入式领用多年, 致力于分享嵌入式领域技术! 388

京东技术产品经理面试全记录:从简历投递到一面45分钟实战复盘

本文深度复盘京东技术产品经理面试全流程,从策略准备、思维题拆解、项目阐述到反问谈判,提供了一套可演练的求职策略体系。文章强调该岗位需具备横跨技术与商业的枢纽能力,并通过“QQ分组vs微信标签”等案例,剖析了产品思维与结构化表达在面试中的关键作用,助力候选人将紧张转化为掌控感。

weixin_29275257的博客 630

Linux编程--IO多路复用

IO多路复用是指通过一种机制,使得单个进程可以监控多个文件描述符的可读、可写和异常等事件。常见的IO多路复用技术包括:select、poll、epoll等。在实际应用中,IO多路复用可以提高程序的运行效率和性能,减少系统开销,降低系统资源的使用率。它广泛应用于网络编程、服务器开发、操作系统等领域,可以帮助开发人员更好地处理大量的网络连接和数据请求。

xinqi_1的博客 2403

YOLOv11多模态融合实战:基于YOLOFuse的RGB与红外线(IR)协同检测技术解析

本文深入解析了YOLOv11多模态融合技术,重点介绍基于YOLOFuse框架的RGB与红外线(IR)协同检测方法。通过动态权重分配、跨模态特征对齐等创新设计,实现在低光照等复杂环境下的高精度目标检测,mAP提升高达37%。文章包含实战案例、训练技巧和部署方案,为计算机视觉开发者提供完整的多模态融合解决方案。

weixin_29038345的博客 290

Robocorp+Robot Framework学习记录【初学者课程:一级课程】

以下内容均来自:https://robotframework.org/?tab=2#getting-started。通过官网的学习和本地实际安装使用体验而来,本文仅记录学习过程。 Robot Framework介绍 Robot Framework 是一个通用的开源自动化框架。它可用于测试自动化和机器人过程自动化 (RPA)。 Robot Framework环境配置及安装 具体请见:Win10环境下安装pytho、pip与Robot Framework 学习过程与等级划分 官方认为Robot Framew.

OwenDom的博客 5374

Linux IO多路复用模型

流指的是可以进行I/O操作的内核对象,例如: 文件,管道和套接字等,流的入口就是文件描述符fd。所有对流的读写操作,我们都可以称之为IO操作。当一个流中, 在没有数据read的时候,或者说在流中已经写满了数据,再write,我们的IO操作就会出现一种现象,就是阻塞现象,如下图。综上,我们整理了7中Server的服务器处理结构模型,每个模型都有各自的特点和优势,那么对于多少应付高并发和高CPU利用率的模型,目前多数采用的是模型五(或模型五进程版,如Nginx就是类似模型五进程版的改版)。

m0_53157173的博客 694

YOLOv11改进 | 引入SFSConv空间频率选择卷积(含SFSC3k2二次创新),空间频率特征协同作用,检测性能全面提升

本文提出在YOLOv11中引入SFSConv空间频率选择卷积模块,通过显式分离和动态融合空间域与频率域特征,解决传统卷积对多尺度目标检测的局限性。SFSConv包含空间频率分离、动态权重融合和协同特征重建三个核心机制,并进一步创新提出SFSC3k2结构,通过双路频率分支增强特征协同作用。该改进显著提升了YOLOv11在遥感、医学等多尺度复杂场景下的检测性能,实验显示在微小目标检测任务中mAP提升5%-10%。代码实现展示了SFSConv模块的核心逻辑及其在PyTorch中的高效实现。

走向CTO的路上... 767

Linux进阶篇:I/O复用

I/O复用是Linux下高效处理多I/O操作的核心技术,允许单个进程/线程同时监控多个文件描述符(fd),仅当某个/某些fd就绪(可读/可写/异常)时,才执行对应的I/O操作。

2403_84469788的博客 708

MetaGPT核心模块:Data Interpreter 上手实战 - 数据分析和可视化(附运行过程详解)

上篇文章我们详细解读了 DataInterpreter 的实现原理(论文),本文将开始上手实操,开始写代码用上 DataInterpreter。从最简单的例子开始,先给大家看下其运行过程,看下DataInterpreter是如何自动拆解任务,完成任务的,帮助大家构建直观认识。

同学小张的博客 371

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

IO多路复用模型实现机制详解(Linux)

select/poll是将表存储在用户层,从用户层到内核层,再由内核层到用户层为两次拷贝极大影响系统性能,效率将降低,然而对于epoll而言,存储文件描述符的表是在内核层且数据结构时间复杂度降低,减少了拷贝开销(select/poll是将整个表来回拷贝,epoll只是将已就绪的拷贝到用户层)。虽然select/poll/epoll在内核层实现机制一样,但由于表的存储方式与位置决定了系统效率与性能。

weixin_63602189的博客 2941

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Linux I/O编程:I/O多路复用与异步 I/O对比

本文将简要介绍 Linux 中的多路复用 I/O 和异步 I/O 模型,并编写示例代码简述。对于网络 I/O,特别是 UDP 和 TCP,多路复用 I/O(如 `select`、`epoll()`)通常是更好的选择。而异步 I/O(如 `libaio`)只建议用在文件和块设备的 I/O 操作。

Where there is life, there is hope. 1446

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Linux下的I/O模型

IO 是 Input/Output 的缩写,指的是输入和输出。在计算机当中,IO 操作通常指将数据从一个设备或文件中读取到计算机内存中,或将内存中的数据写入设备或文件中。这些设备可以包括硬盘驱动器、网卡、键盘、屏幕等。通常用户进程中的一个完整I/O分为两个阶段:用户进程空间→内核空间→设备空间。

m0_74976404的博客 1543

Linux——I/O复用

I/O复用(Input/Output Multiplexing)是一种高效处理多个I/O操作的机制,允许单个进程或线程同时监控多个文件描述符(如套接字、管道等),并在这些描述符中的任意一个准备好进行读写操作时通知程序。其核心目标是减少系统资源消耗,避免为每个I/O操作创建独立的线程或进程,从而提升并发性能。

m0_74774362的博客 1267

Linux I/O模型总结

Linux I/O模型分为五种:阻塞I/O(全程阻塞)、非阻塞I/O(轮询检查)、I/O多路复用(代理监控)、信号驱动I/O(信号通知)和异步I/O(内核全处理)。其中I/O多路复用(特别是epoll)是高并发网络服务的首选,而异步I/O理论性能最优但实现不完善。各模型在阻塞阶段、轮询需求和适用场景上存在差异,需根据实际需求选择。

qq_52537313的博客 913

【Linux】I/O多路复用模型 select、poll、epoll

在监听 socket 时,需要分配多个线程/进程维护多个 socket 连接,I/O 多路复用技术就是用来使用一个进程来监听维护多个 socket 连接 多路: I/O 状态:可读、可写 复用: 使用一个线程/进程监听处理 I/O 事件,复用多个 socket 请求 一、select 模型 select 原理: 1.创建一个文件描述符集合 fd_set set 0 不监听 1 监听 2.设置文件描述符的状态 FD_ZERO(&set); 初始化监听集合,将位码初始化为 0 FD_SET(int s

努力让自己的能力配得上梦想. 1485

Linux-I O模型详解_linux i o模型

说到I/O模型,都会牵扯到同步、异步、阻塞、非阻塞这几个词,以下讲解这几个词的概念。阻塞和非阻塞阻塞和非阻塞指的是执行一个操作时等操作结束再返回结果,还是马上返回结果。**阻塞(blocking):**指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起(当前线程进入非可执行状态,在这个状态,CPU不会分配时间片,线程暂停运行)只有到到结果才进入活动状态;

2401_89733851的博客 1341

【Linux】阻塞I/O模型、非阻塞I/O模型、I/O复用模型、信号驱动I/O模型、异步I/O模型 概念普及

link 2、深入理解分析     回来以后,赶紧上网好好查查,加深学习一下。这两个概念在工作中经常用到这些,例如在linux网络IO中涉及到如下模型: (1)阻塞式 IO (2)非阻塞式IO (3)IO多路复用 (4)信号驱动IO (5)异步IO 在知乎上面看到一些解释如下: 截图如下: 3、总结      同步和异步针对应用程序来,关注的是程序中...

sowhat 989

【重要】Linux I/O模型

socket阻塞与非阻塞,同步与异步、I/O模型 分类: c/c++ socket网络编程2012-04-12 16:35 32926人阅读 评论(22) 收藏 举报 socketsocketswindowsapi服务器 目录(?)[+] socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理解

心之所向,身之所往 2188

Java NIO编程理论基础篇——Java I/O的发展以及linux网络I/O模型

发展简述: Java在jdk1.4之前,Java对I/O的支持并不完善,开发人员会遇到许多问题,例如: 没有数据缓冲区,性能较低; 没有C或者C++中的Channel概念,通常 ...

sdr_zd的博客 5677

Linux的I/O模型笔记

Linux系统提供了五种I/O模型,主要区别在于数据就绪和数据处理的方式:1)阻塞I/O会挂起进程直至数据就绪;2)非阻塞I/O会立即返回结果,需轮询检查;3)复用式I/O通过select/epoll集中管理多个I/O;4)信号驱动I/O通过内核信号通知就绪状态;5)异步I/O由内核完成全部操作后通知进程。其中阻塞和非阻塞模型适合简单场景,复用式适合高并发,信号驱动和异步I/O则能进一步提升效率。理解这些模型有助于针对不同场景优化I/O性能。

qq_52763245的博客 1037

Linux 中的五种 I/O 模型

阻塞 I/O 模型、非阻塞 I/O 模型、I/O 复用模型、信号驱动 I/O 模型、异步 I/O 模型

We choose to go to the moon in this decade and do the other things, not because they are easy, but beacase they are hard. 2008

Linux五 ——I/O复用

Linux五 ——I/O复用

weixin_43662553的博客 760
上一篇: Windows 是最安全的操作系统
下一篇: 深入Windows APC
pythonxxoo
博客等级 码龄5年 337粉丝 670原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值