【计算机网络】高级IO模型
高级IO模型
- 一、 理解 IO
- 二、认识五种高级 IO 模型
- 1. 阻塞 IO
- 2. 非阻塞IO
- 3. 信号驱动 IO
- 4. IO 多路转接
- 5. 异步 IO
- 三、高级 IO 重要概念
- 1. 阻塞和非阻塞
- 2. 同步通信和异步通信
- 四、非阻塞 IO
- fcntl
一、 理解 IO
当我们调用系统接口 write、read 的时候,本质是把数据从用户层写给操作系统,也就是写入到 OS 的发送缓冲区中,或者从 OS 的接收缓冲区中读取数据,所以它们的本质也就是拷贝函数。
那么在这个过程中,调用 write 的时候只有当发送缓冲区中有足够的空间才能进行拷贝,当发送缓冲区没有空间了,此时 write 只能阻塞等待,不能继续拷贝。而调用 read 的时候,只有当接收缓冲区有数据才能进行读取拷贝,当接收缓冲区没有数据了,此时 read 也只能阻塞等待。上面就是 IO 的过程,所以,IO 的过程被分为两个部分:等待和拷贝!
所以在 IO 的过程中,要进行拷贝,必须先判断条件成立,也就是读写事件是否就绪。那么什么叫做高效的 IO 呢?就是在单位时间内,IO 过程中,等的比重越小,IO 的效率越高!
二、认识五种高级 IO 模型
1. 阻塞 IO
在内核将数据准备好之前,系统调用会一直等待。所有的套接字,默认都是阻塞方式。
阻塞IO是最常见的IO模型,过程如下:

2. 非阻塞IO
非阻塞 IO 就是,如果内核还未将数据准备好,系统调用仍然会直接返回,并且返回 EWOULDBLOCK 错误码。
非阻塞 IO 往往需要程序员循环的方式反复尝试读写文件描述符,这个过程称为轮询。这对 CPU 来说是较大的浪费,一般只有特定场景下才使用。

3. 信号驱动 IO
内核将数据准备好的时候,使用 SIGIO 信号通知应用程序进行 IO 操作。

4. IO 多路转接

IO 多路转接,虽然从流程图上看起来和阻塞 IO 类似,实际上最核心在于 IO 多路转接能够同时等待多个文件描述符的就绪状态。
5. 异步 IO
由内核在数据拷贝完成时,通知应用程序。和信号驱动 IO 的区别在于,信号驱动是告诉应用程序何时可以开始拷贝数据。

以上就是五种高级 IO 的模型的简单介绍。任何 IO 过程中,都包含两个步骤:第一是等待,第二是拷贝。而且在实际的应用场景中,等待消耗的时间往往都远远高于拷贝的时间。想要让 IO 更高效,最核心的办法就是让等待的时间尽量少。
三、高级 IO 重要概念
1. 阻塞和非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。
- 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回
- 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程
其实阻塞IO和非阻塞IO的效率是差不多的,因为 IO = 等待+拷贝,数据好了大家都要拷贝,只是非阻塞IO在等待的时候可以做其他事情,也就是它们之间等的方式不一样,非阻塞IO在进行非阻塞轮询时可以做自己其它的事情,所以这就导致非阻塞IO在效率上稍微高一点。
2. 同步通信和异步通信
同步和异步关注的是消息通信机制。
- 所谓同步IO,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了;换句话说,就是由调用者主动等待这个调用的结果。也就是参与了IO中的等待或者拷贝的过程,就是同步IO;
- 异步IO则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果;换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果;而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。也就是说,异步IO不参与IO,只是发起IO,最后拿结果就行。
四、非阻塞 IO
fcntl
我们以前学过 recv() 这样的接口,其中它的参数如下:

我们知道前三个参数是和 read() 的一模一样,而最后一个参数 flag 设为 0 默认就是阻塞等待。而我们可以将这个参数设为 MSG_DONTWAIT,就是非阻塞IO,如下:

但是这种选项用起来不方便,更通用的做法是使用 fcntl() 接口。我们知道,文件描述符就是一个数组下标,而我们所有的网络通信、文件等等,都是读写文件描述符,而每一个文件描述符指向的都是内核中的文件对象,文件对象是有关于这个文件的 flags 的,也就是它的标记位。所以我们可以通过 fcntl() 接口来直接设置一个文件描述符的属性!其实就是设置其文件对象中的 flags 标志位,告诉内核这个指定的文件描述符要以非阻塞的方式来操作。系统接口如下:

如上,可以按照指定的 cmd 来对指定的文件描述符来进行可变参数部分的设置。
传入的 cmd 的值不同,后面追加的参数也不相同。fcntl 函数有5种功能:
- 复制一个现有的描述符(cmd=F_DUPFD)
- 获得/设置文件描述符标记(cmd=F_GETFD 或 F_SETFD)
- 获得/设置文件状态标记(cmd=F_GETFL 或 F_SETFL)
- 获得/设置异步 I/O 所有权(cmd=F_GETOWN 或 F_SETOWN)
- 获得/设置记录锁(cmd=F_GETLK,F_SETLK 或 F_SETLKW)
我们尝试将标准输入设置为非阻塞IO的形式,如下代码:
void SetNonBlock(int fd){// 获取文件状态标记位int fl = fcntl(fd, F_GETFL);if(fl < 0){perror("fcntl");return;}// 对获取到的文件状态标记位追加属性标记位fcntl(fd, F_SETFL, fl | O_NONBLOCK);cout << " set " << fd << " nonblock done " << endl;}int main(){char buffer[1024];// 设置标准输入为非阻塞IOSetNonBlock(0);while(true){cout << "Please Enter# ";ssize_t n = read(0, buffer, sizeof(buffer) - 1);if(n > 0){buffer[n - 1] = 0;cout << "echo: " << buffer << endl;}else if(n == 0){cout << "read done" << endl;break;}else{cerr << "read error, n = " << n << ", errno code: " << errno << ", errstr: " << strerror(errno) << endl;break;}}return 0;}
上面的代码其实是跑不通的,因为我们根本没有输入数据,因此 n 是小于0的,我们可以通过打印错误信息观察:

我们可以看到,错误码的描述大概意思就是临时资源不可用,因为我们在 else 中 break 了,我们应该把 break 去掉,改为 sleep(1),我们方便观察。
此时运行后我们在键盘上输入是可以直接回显的,如下:

所以,设置为非阻塞,如果底层 fd 数据没有就绪,recv/read/write/send,返回值会以出错的形式返回。所以出错就分为两种情况了,一种是真的出错了,另一种是底层没有就绪,这种情况就是返回 11 号错误码,也就是 EWOULDBLOCK. 那么我们怎么区分呢?可以通过 errno 区分!如果 errno 为 11,代表底层没就绪!所以我们对代码稍作修改,如下:
void SetNonBlock(int fd){// 获取文件状态标记位int fl = fcntl(fd, F_GETFL);if(fl < 0){perror("fcntl");return;}// 对获取到的文件状态标记位追加属性标记位fcntl(fd, F_SETFL, fl | O_NONBLOCK);cout << " set " << fd << " nonblock done " << endl;}int main(){char buffer[1024];// 设置标准输入为非阻塞IOSetNonBlock(0);while(true){// cout << "Please Enter# ";ssize_t n = read(0, buffer, sizeof(buffer) - 1);if(n > 0){buffer[n - 1] = 0;cout << "echo: " << buffer << endl;}else if(n == 0){cout << "read done" << endl;break;}else{if(errno == EWOULDBLOCK){// do other thing...}else{cerr << "read error" << endl;break;}//cerr << "read error, n = " << n << ", errno code: " << errno << ", errstr: " << strerror(errno) << endl;sleep(1);}}return 0;}
相关文章:
【计算机网络】高级IO模型
高级IO模型 一、 理解 IO二、认识五种高级 IO 模型1. 阻塞 IO2. 非阻塞IO3. 信号驱动 IO4. IO 多路转接5. 异步 IO 三、高级 IO 重要概念1. 阻塞和非阻塞2. 同步通信和异步通信 四、非阻塞 IOfcntl 一、 理解 IO 当我们调用系统接口 write、read 的时候,本质是把数…...
LabVIEW电动汽车直流充电桩监控系统
LabVIEW电动汽车直流充电桩监控系统 随着电动汽车的普及,充电桩的安全运行成为重要议题。通过集成传感器监测、单片机技术与LabVIEW开发平台,设计了一套电动汽车直流充电桩监控系统,能实时监测充电桩的温度、电压和电流,并进行数…...
前端学习<二>CSS基础——08-CSS属性:定位属性
CSS的定位属性有三种,分别是绝对定位、相对定位、固定定位。 position: absolute; <!-- 绝对定位 -->position: relative; <!-- 相对定位 -->position: fixed; <!-- 固定定位 --> 下面逐一介绍。 相对定位 相对定位:让…...
88. 合并两个有序数组(javascript)
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意:最终,合并后数组…...
机器学习_集成学习_梯度提升_回归_决策树_XGBoost相关概念
目录 1. 机器学习 使用监督吗?什么又是监督学习? 2. 与XGBoost 类似的机器学习方法有哪些? 3. 随机森林方法 和 梯度提升方法 有什么区别? 分别应用于什么场景? 4. 决策树回归方法 和 Gradient Boosting类回归方法…...
ABAP 字段类型不一样导致相加之后金额错误
文章目录 ABAP 字段类型不一样导致相加之后金额错误写在前面的总结示例程序1汇总MSEG表和MLDOC表 ABAP 字段类型不一样导致相加之后金额错误 写在前面的总结 如果需要不同底表的字段相加的值,那么最好是根据条件去分别算出那些值放在临时内表里面,再去…...
【L1距离和L2距离】Manhattan Distance Euclidean Distance 解释和计算公式
距离度量 特征空间中两个实例点的距离可以反映出两个实力点之间的相似性程度,使用的距离可以是欧式距离,也可以是其他距离。 欧氏距离(L2距离):最常见的两点之间或多点之间的距离表示法,又称之为欧几里得度量,它定义于…...
自动发卡平台源码优化版,支持个人免签支付
源码下载地址:自动发卡平台源码优化版.zip 环境要求: php 8.0 v1.2.6◂ 1.修复店铺共享连接时异常问题 2024-03-13 23:54:20 v1.2.5 1.[新增]用户界面硬币增款扣款操作 2.[新增]前台对接库存信息显示 3.[新增]文件缓存工具类[FileCache] 4.[新增]库存同…...
如何使用固定公网地址远程连接Python编译器并将运行结果返回到Pycharm
文章目录 一、前期准备1. 检查IDE版本是否支持2. 服务器需要开通SSH服务 二、Pycharm本地链接服务器测试1. 配置服务器python解释器 三、使用内网穿透实现异地链接服务器开发1. 服务器安装Cpolar2. 创建远程连接公网地址 四、使用固定TCP地址远程开发 本文主要介绍如何使用Pych…...
Java设计模式—备忘录模式(快照模式)
定义 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,很多软件都提供了撤销(Undo)操作&#…...
没学数模电可以玩单片机吗?
我们首先来看一下数电模电在单片机中的应用。数电知识在单片机中主要解决各种数字信号的处理、运算,如数制转换、数据运算等。模电知识在单片机中主要解决各种模拟信号的处理问题,如采集光照强度、声音的分贝、温度等模拟信号。而数电、模电的相互转换就…...
FlinkSQL之Flink SQL Join二三事
Flink SQL支持对动态表进行复杂而灵活的连接操作。 为了处理不同的场景,需要多种查询语义,因此有几种不同类型的 Join。默认情况下,joins 的顺序是没有优化的。表的 join 顺序是在 FROM 从句指定的。可以通过把更新频率最低的表放在第一个…...
某某消消乐增加步数漏洞分析
一、漏洞简介 1) 漏洞所属游戏名及基本介绍:某某消消乐,三消游戏,类似爱消除。 2) 漏洞对应游戏版本及平台:某某消消乐Android 1.22.22。 3) 漏洞功能:增加游戏步数。 4…...
SpringBoot动态数据源实现
一、背景 一个应用难免需要连接多个数据库,像我们系统起码连接了5个以上数据库,AWS RDS主库,ECS自搭MySQL从库,工厂系统三个SQLServer数据库,在线网站MySQL数据库,记得很早以前是用SessionFactory配置&…...
计算机网络常见题(持续更新中~)
1 描述一下HTTP和HTTPS的区别 2 Cookie和Session有什么区别 3 如果没有Cookie,Session还能进行身份验证吗? 4 BOI,NIO,AIO分别是什么 5 Netty的线程模型是怎么样的 6 Netty是什么?和Tomcat有什么区别,特点是什么? 7 TCP的三次…...
富格林:可信招数揭发防备暗箱陷阱
富格林悉知,在风云变幻的金融市场中,炒贵金属是一项具有高收益潜力的投资方式。但投资是风险与收益共存的,因此我们在做单投资过程中需总结可信招数揭发暗箱陷阱,防备受害亏损。以下总结几点可信的投资技巧,希望能够帮…...
获取高德安全码SHA1
高德开发者平台上给的三种方法 获取安全码SHA1,这里我自己使用的是第三种方法。 1、通过Eclipse编译器获取SHA1 使用 adt 22 以上版本,可以在 eclipse 中直接查看。 Windows:依次在 eclipse 中打开 Window -> Preferances -> Androi…...
关于RPC
初识RPC RPC VS REST HTTP Dubbo Dubbo 特性: 基于接口动态代理的远程方法调用 Dubbo对开发者屏蔽了底层的调用细节,在实际代码中调用远程服务就像调用一个本地接口类一样方便。这个功能和Fegin很类似,但是Dubbo用起来比Fegin还要简单很多&a…...
pulsar: kafka on pulsar之把pulsar当kafka用
一、下载协议包(要和pulsar版本比较一致) https://github.com/streamnative/kop/releases?q2.8.0&expandedtrue二、在pulsar的根目录创建一个protocols目录,将上述包放到这个目录里 三、编辑broker.conf(如果是集群)或者standalone.con…...
七月论文审稿GPT第4版:通过paper-review数据集微调Mixtral-8x7b
模型训练 Mixtral-8x7b地址:魔搭社区 GitHub: hiyouga/LLaMA-Factory: Unify Efficient Fine-tuning of 100 LLMs (github.com) 环境配置 git clone https://github.com/hiyouga/LLaMA-Factory.git conda create -n llama_factory python3.10 conda activate lla…...
Windows下frp客户端静默启动全攻略:VBS脚本+开机自启一步到位
Windows下frp客户端静默启动全攻略:VBS脚本开机自启一步到位 在远程办公和内网穿透场景中,frp作为一款高性能的反向代理工具,其客户端的稳定运行至关重要。许多Windows系统管理员都遇到过这样的困扰:每次服务器重启后需要手动运行…...
智能客服新利器:用Qwen3-VL-8B搭建截图问答系统,纯本地运行
智能客服新利器:用Qwen3-VL-8B搭建截图问答系统,纯本地运行 1. 项目背景与核心价值 在电商客服、技术支持等场景中,用户经常通过截图提出问题。传统客服需要人工查看图片并回复,效率低下且成本高昂。Qwen3-VL-8B多模态模型的出现…...
pgModeler插件开发教程:如何扩展你的数据库建模工具功能
pgModeler插件开发教程:如何扩展你的数据库建模工具功能 【免费下载链接】pgmodeler Open-source data modeling tool designed for PostgreSQL. No more typing DDL commands. Let pgModeler do the work for you! 项目地址: https://gitcode.com/gh_mirrors/pg/…...
Ansys Zemax | 如何寻找几何错误
概要这篇文章讲解了:在非序列模式中造成几何错误(错误10561)的各种原因。如何诊断这些错误。介绍使用 OpticStudio 做设计的时候,必须得知道得到的结果是否是正确的。尤其是在非序列模式下,复杂的几何模型可以互相嵌套…...
使用Cosmos-Reason1-7B自动化批改编程作业:代码逻辑与风格检查
使用Cosmos-Reason1-7B自动化批改编程作业:代码逻辑与风格检查 1. 引言 如果你是计算机课程的老师,或者负责带学生做项目,那你肯定对批改编程作业这件事深有体会。几十份、上百份代码看下来,眼睛都花了。更头疼的是,…...
毕设程序java基于Web的宠物医院管理系统 SpringBoot驱动的宠物诊疗服务平台设计与实现 智能化宠物医疗健康档案管理系统开发
毕设程序java基于Web的宠物医院管理系统c692jn28 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着社会经济发展和生活水平提升,宠物已成为众多家庭的重要成员&…...
Rigol DHO1000系列示波器实测:12-bit高分辨率到底有多香?
Rigol DHO1000系列示波器实测:12-bit高分辨率如何重塑精密测量体验 当你在调试一个微弱的生物电信号传感器,或是排查物联网设备的低功耗射频干扰时,传统8-bit示波器上那些模糊的波形轮廓是否曾让你陷入"猜谜游戏"?去年我…...
开箱即用!圣女司幼幽-造相Z-Turbo镜像部署,快速体验文生图魅力
开箱即用!圣女司幼幽-造相Z-Turbo镜像部署,快速体验文生图魅力 1. 引言:从想法到画面,只需几分钟 你有没有过这样的时刻?脑海里浮现出一个绝妙的画面:一位身着墨绿长裙、手持长剑的仙子,发丝在…...
PHP-Resque源码解析:深入剖析核心类Resque_Job和Resque_Worker的实现原理
PHP-Resque源码解析:深入剖析核心类Resque_Job和Resque_Worker的实现原理 【免费下载链接】php-resque PHP port of resque (Workers and Queueing) 项目地址: https://gitcode.com/gh_mirrors/ph/php-resque PHP-Resque是Redis支持的PHP后台作业处理库&…...
Bilibili视频下载完整指南:如何用开源工具高效获取优质内容
Bilibili视频下载完整指南:如何用开源工具高效获取优质内容 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirr…...
