linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO

非阻塞IO(NIO) 也称作同步阻塞IO。 阅读详情


IO概念


Linux的内核将所有外部设备都可以看做一个文件来操作。那么我们对与外部设备的操作都可以看做对文件进行操作。我们对一个文件的读写,都通过调用内核提供的系统调用;内核给我们返回一个file descriptor(fd,文件描述符)。而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符)。描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性)。那么我们的应用程序对文件的读写就通过对描述符的读写完成。

 linux将内存分为内核区,用户区。linux内核给我们管理所有的硬件资源,应用程序通过调用系统调用和内核交互,达到使用硬件资源的目的。应用程序通过系统调用read发起一个读操作,这时候内核创建一个文件描述符,并通过驱动程序向硬件发送读指令,并将读的的数据放在这个描述符对应结构体的内核缓存区中,然后再把这个数据读到用户进程空间中,这样完成了一次读操作;

但是大家都知道I/O设备相比cpu的速度是极慢的。linux提供的read系统调用,也是一个阻塞函数。这样我们的应用进程在发起read系统调用时,就必须阻塞,就进程被挂起而等待文件描述符的读就绪,那么什么是文件描述符读就绪,什么是写就绪?

读就绪:就是这个文件描述符的接收缓冲区中的数据字节数大于等于套接字接收缓冲区低水位标记的当前大小;

写就绪:该描述符发送缓冲区的可用空间字节数大于等于描述符发送缓冲区低水位标记的当前大小。(如果是socket fd,说明上一个数据已经发送完成)。

接收低水位标记和发送低水位标记:由应用程序指定,比如应用程序指定接收低水位为64个字节。那么接收缓冲区有64个字节,才算fd读就绪;

综上所述,一个基本的IO,它会涉及到两个系统对象,一个是调用这个IO的进程对象,另一个就是系统内核(kernel)。当一个read操作发生时,它会经历两个阶段:

  • 通过read系统调用想内核发起读请求。
  • 内核向硬件发送读指令,并等待读就绪。 
  • 内核把将要读取的数据复制到描述符所指向的内核缓存区中。
  • 将数据从内核缓存区拷贝到用户进程空间中。

IO模型


在linux系统下面,根据IO操作的是否被阻塞以及同步异步问题进行分类,可以得到下面五种IO模型:
1、阻塞I/O模型
最流行的I/O模型是阻塞I/O模型,缺省情形下,所有文件操作都是阻塞的。我们以套接口为例来讲解此模型。在进程空间中调用recvfrom,其系统调用直到数据报到达且被拷贝到应用进程的缓冲区中或者发生错误才返回,期间一直在等待。我们就说进程在从调用recvfrom开始到它返回的整段时间内是被阻塞的。

2、非阻塞I/O模型
进程把一个套接口设置成非阻塞是在通知内核:当所请求的I/O操作不能满足要求时候,不把本进程投入睡眠,而是返回一个错误。也就是说当数据没有到达时并不等待,而是以一个错误返回。

3、I/O复用模型
linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select;这样select/poll可以帮我们侦测许多fd是否就绪。但是select/poll是顺序扫描fd是否就绪,而且支持的fd数量有限。linux还提供了一个epoll系统调用,epoll是基于事件驱动方式,而不是顺序扫描,当有fd就绪时,立即回调函数rollback;

4、信号驱动异步I/O模型
首先开启套接口信号驱动I/O功能, 并通过系统调用sigaction安装一个信号处理函数(此系统调用立即返回,进程继续工作,它是非阻塞的)。当数据报准备好被读时,就为该进程生成一个SIGIO信号。随即可以在信号处理程序中调用recvfrom来读数据报,井通知主循环数据已准备好被处理中。也可以通知主循环,让它来读数据报。

5、异步I/O模型
告知内核启动某个操作,并让内核在整个操作完成后(包括将数据从内核拷贝到用户自己的缓冲区)通知我们。这种模型与信号驱动模型的主要区别是:信号驱动I/O:由内核通知我们何时可以启动一个I/O操作;异步I/O模型:由内核通知我们I/O操作何时完成。


非阻塞IO详解


通过上面,我们知道,所有的IO操作在默认情况下,都是属于阻塞IO。尽管上图中所示的反复请求的非阻塞IO的效率底下(需要反复在用户空间和进程空间切换和判断,把一个原本属于IO密集的操作变为IO密集和计算密集的操作),但是在后面IO复用中,需要把IO的操作设置为非阻塞的,此时程序将会阻塞在select和poll系统调用中。把一个IO设置为非阻塞IO有两种方式:在创建文件描述符时,指定该文件描述符的操作为非阻塞;在创建文件描述符以后,调用fcntl()函数设置相应的文件描述符为非阻塞。
创建描述符时,利用open函数和socket函数的标志设置返回的fd/socket描述符为O_NONBLOCK。
int sd=socket(int domain, int type|O_NONBLOCK, int protocol);
int fd=open(const char *pathname, int flags|O_NONBLOCK);
创建描述符后,通过调用fcntl函数设置描述符的属性为O_NONBLOCK
#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

//例子
if (fcntl(fd, F_SETFL, fcntl(sockfd, F_GETFL, 0)|O_NONBLOCK) == -1) {
	return -1;
}
	return 0;
}


IO复用详解


在IO编程过程中,当需要处理多个请求的时,可以使用多线程和IO复用的方式进行处理。上面的图介绍了整个IO复用的过程,它通过把多个IO的阻塞复用到一个select之类的阻塞上,从而使得系统在单线程的情况下同时支持处理多个请求。和多线程/进程比较,I/O多路复用的最大优势是系统开销小,系统不需要建立新的进程或者线程,也不必维护这些线程和进程。IO复用常见的应用场景:
  1. 客户程序需要同时处理交互式的输入和服务器之间的网络连
【操作系统】IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析 阅读详情

相关推荐

GEOS-Chem笔记——模式下载安装+驱动数据+运行流程

看过我博客的会发现我写了很多CESM的笔记,但是说实话,平时科研我其实更多时候是GEOS-Chemuser。之所以写了很多CESM笔记,其实是因为不会,就边学边写。然后GEOS-Chem已经用比较熟了,所以也没想过做笔记啥的。但是我发现越来越多朋友私信我各种CESM问题,我觉得我可能给大家营造了一种我是CESM达人的错觉。感觉自己有点跑偏了呢。公平起见,我觉得我有必要补充点GEOS-Chem笔记。 GEOS-Chem是研究大气化学的人常用的大气化学传输模式,在全世界范围的大气化学研究组中被广泛使用。不过.

砍柴姑娘Jourosy的博客 1万+

ComfyUI面部修复FaceDetailer保姆级教程:从模型选择到参数调优全解析

本文提供ComfyUI面部修复FaceDetailer的保姆级教程,深度解析从模型选择到参数调优的全过程。针对常见的五官模糊、肤色不均等问题,详细对比了BBox与Segm检测器的优劣,并给出SD1.5与SDXL模型的核心参数联动策略与实战方案,帮助用户精准掌控AI绘画中的面部修复效果。

weixin_29073241的博客 471

字符集的选择

字符集的选择 一:背景介绍 DICOM特定字符集(0008,0005) 此标签获得不同的值就代表使用不同的语言进行解码。 以下为多家CT厂商的(0008,0005)取值: 字符集: unicode是字符集,ASCII、GB2312、GBK、GB18030既是字符集也是编码方式,UTF-8只是编码方式。 二:中文字符集介绍 世界通用字符集——UTF 中文字符集——GB2312、GBK、GB18030 字符集的详细介绍 一:UTF-8 程序是把一个字节一个字节的来读取,然后再根据字节中开头的bit

qq_41972968的博客 1519

Solidworks钣金设计:折弯系数、K因子与折弯扣除的实战应用解析

本文深入解析Solidworks钣金设计中折弯系数、K因子与折弯扣除的核心概念与实战应用。通过厘清三者间的逻辑关系与换算方法,并结合材料特性、工艺参数及车间实测,指导工程师精准确定展开长度,确保设计图纸与加工实物的一致性,有效提升钣金件设计精度与生产效率。

weixin_29268267的博客 921

片上眼图(Eye-opening monitor)

当它们值不同的时候error counter +1,通过统计RX到的码元个数、error counter,可以获得offset sampler上下左右不停的调整位置时的一个误码率(BER),通过这个误码率去描绘出眼图。如上图所示,eye-scan RX端 offset sampler独立且并行的和使用CDR sample的采样电路一起跑,offset-sampler可以任意调整水平(time)和垂直(voltage)方向的偏移(如下图所示),在一个UI内产生一个全新的sample点。

沈土豪的书屋 4415

构建高可用CephFS NFS网关:NFS-Ganesha与RADOS集群的深度整合

本文详细介绍了如何构建高可用的CephFS NFS网关,通过NFS-Ganesha与RADOS集群的深度整合,实现高效文件共享。文章涵盖核心架构、部署实战、性能调优及避坑指南,帮助用户解决Ceph客户端兼容性问题,提升存储访问效率。特别强调高可用设计,确保服务稳定性,适用于金融、电商等高要求场景。

weixin_26976635的博客 254

科研绘图系列:R语言绘制宏基因组分析的可视化图形(network & barplot & heatmap)

科研绘图系列:R语言多图形组合(network & barplot & heatmap)

专注生信领域 644

实战落地!Python抓取股票历史数据:开盘/收盘/成交量全维度爬取(附数据清洗+可视化)

股票历史数据抓取的核心是“数据准确性+完整性”,网页爬取适合小批量、个性化需求,API调用适合批量、标准化需求。多市场数据抓取:适配港股(00700.HK)、美股(AAPL)的抓取逻辑;高频数据抓取:抓取分钟级、小时级行情数据,用于短线量化策略;财务数据扩展:抓取市盈率、市净率、净利润等财务指标,结合价格数据做基本面分析;量化策略回测:将清洗后的数据接入Backtrader、VNPY等量化框架,验证策略有效性。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1739

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

计算机控制技术及应用

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

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
下一篇: linux基础编程:进程通信之套接字
ColZer
博客等级 码龄14年 42粉丝 16原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值