当前位置:网站首页>高效IO模型
高效IO模型
2022-08-04 03:05:00 【秃头宇】
文章目录
前言
IO过程总体分为两步,第一步等:接收端->接受缓冲区等待数据的递达,发送端->等待发送缓冲区有可用空间,将发送数据放入发送缓冲区;第二步拷贝:接收端->将递达的数据从内核空间拷贝到用户空间的接受缓冲区,发送端->将发送的数据从用户空间的发送缓冲区拷贝至内核缓冲区;
所以高效IO本质是单位时间内拷贝的频率很高,重点是缩短等待的时间
一、五种IO模型
1.1 阻塞IO
阻塞IO是最常见的IO模型(在内核将数据准备好之前,系统调用会一直等待,所有的套接字,默认都是阻塞方式)
阻塞:本质是由OS发起,由OS执行,进程状态R->(S or T or D),进入等待队列当中,数据就绪后,进程被操作系统唤醒,再去执行
recvfrom
1.2 非阻塞IO
如果内核还未将数据准备好,系统调用仍然会直接返回,并且返回EWOULDBLOCK
非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符, 这个过程称为轮询. 这对CPU来说是较大的浪费, 一般只有特定场景下才使用
非阻塞轮询的本质是:由用户发起,OS执行,做事件就绪(OS有数据)的检测工作
1.3 信号驱动IO
内核将数据准备好的时候,使用SIGIO信号通知应用程序进行IO操作
1.4 异步IO
由内核在数据拷贝完成时,通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据)
1.5 IO多路转接
虽然从流程图上看起来和阻塞IO类似. 实际上最核心在于IO多路转接能够同时等待多个文件
描述符的就绪状态
二、同步通信与异步通信
同步与异步关注的是消息通信机制
- 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回,就得到返回值;换句话说,就是由调用者主动等待这个调用的结果;拷贝需要用户参与
- 异步则是相反,调用在发出之后,这个调用就直接返回了,所有没有返回结果;换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果;而是在调用发出后,被调用者通过状态、通知来通知调用者,或者通过回调函数处理这个调用。拷贝不需要用户参与,操作系统拷贝
这里的同步通信和进程之间的同步是完全不相干的概念
三、非阻塞IO
非阻塞IO可以open打开时设置flag
为非阻塞,这里主要介绍打开后的fd如何设置为非阻塞
3.1 fcntl
一个文件描述符,默认都是阻塞IO,fcntl函数用于已经打开的fd
该函数是一个系统调用函数
man 2 fcntl
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
fcntl
函数有5种功能:
- 复制一个现有的描述符 ---- cmd=F_DUPFD
- 获得/设置文件描述符标记–cmd=F_GETFD或F_SETFD
- 获得/设置文件状态标记-----cmd=F_GETFL或F_SETFL
- 获得/设置异步IO所有权-----cmd=F_GETOWN或F_SETOWN
- 获得/设置记录锁--------------cmd=F_GETLK,F_SETLK或F_SETLKW
传入的cmd的值不同,后面追加的参数也不相同
目前只使用第三种功能,获取/设置文件状态标记,就可以将一个文件描述符设置为非阻塞
3.2 实现函数SetNoBlock
基于fcntl
,实现一个SetNoBlock函数,将文件描述符设置为非阻塞
void SetNoBlock(int fd){
int fl = fcntl(fd,F_GETFL); //获取fd的状态标记
if(fl < 0){
perror("fcntl");
return ;
}
fcntl(fd, F_SETFL, fl | O_NONBLOCK); //将fl状态标记设置为非阻塞
}
3.3 如何使用函数SetNoBlock
以轮询的方式读取标准输入
#include<iostream>
#include<unistd.h>
#include<fcntl.h>
bool SetNonBlock(int fd){
int fl = fcntl(fd,F_GETFL);
if(fl < 0){
std::cerr << "fcntl error" << std::endl;
return false;
}
fcntl(fd,F_SETFL, fl | O_NONBLOCK);
return true;
}
int main()
{
#define NUM 1024
SetNonBlock(0);
while(true){
char buffer[NUM];
ssize_t size = read(0,buffer,sizeof(buffer)-1);
if(size < 0){
//不一定是出错了,有可能是底层没有数据
if(errno == EAGAIN || errno == EWOULDBLOCK ){
std::cout << "底层的数据没有就绪,你在轮询检测一下,try again " << std::endl;
continue;
}
if(errno == EINTR){
std::cout << "底层数据就绪未知,被信号中断 " << std::endl;
continue;
}
else{
std::cerr << "read error: " << size << " errno: "<< errno << std::endl;
break;
}
}
buffer[size] = 0; //主动给字符串最后添加'\0'
std::cout << "#echo: " <<buffer << std::endl;
}
return 0;
}
如果以非阻塞读取数据时,如果数据没有就绪,read是以出错的形式返回
如何判断是read真的出错?or 底层数据没有就绪 or read被信号中断
- errno == EAGAIN || errno == EWOULDBLOCK 时,说明数据没有就绪
- errno == EINTR ,说明被信号中断
grep -ER 'EAGAIN | EWOULDBLOCK' /usr/include/ 查看宏定义
边栏推荐
- Zabbix set up email alert + enterprise WeChat alert
- 【指针内功修炼】深度剖析指针笔试题(三)
- LeetCode每日一题(2285. Maximum Total Importance of Roads)
- sql注入一般流程(附例题)
- 逻辑漏洞----其他类型
- Pine Script | How to display and typeset a plot switch?
- 仿牛客论坛项目梳理
- flinkcdc 消费 mysql binlog 没有 sqltype=delete 的数据是什么原
- Flink原理流程图简单记录
- [Playwright Test Tutorial] 5 minutes to get started
猜你喜欢
sqoop ETL工具
2022年最新海南建筑八大员(材料员)模拟考试试题及答案
tkmapper的crud示例:
C program compilation and predefined detailed explanation
跨境电商看不到另一面:商家刷单、平台封号、黑灰产牟利
《nlp入门+实战:第八章:使用Pytorch实现手写数字识别》
new Date将字符串转化成日期格式 兼容IE,ie8如何通过new Date将字符串转化成日期格式,js中如何进行字符串替换, replace() 方法详解
2022年T电梯修理考题及答案
C语言--环形缓存区
Development of Taurus. MVC WebAPI introductory tutorial 1: download environment configuration and operation framework (including series directory).
随机推荐
ant-design的Select组件采用自定义后缀图标(suffixIcon属性)时,点击该自定义图标没有反应,不会展示下拉菜单的问题
架构实战营模块三作业
跨境电商看不到另一面:商家刷单、平台封号、黑灰产牟利
2022焊工(初级)上岗证题目模拟考试平台操作
In a more general sense, calculating the displacement distance and assumptions
[Original] Start the XPS/OXPS reader that comes with Windows 10
创新互融|华秋赋能助力OpenHarmony生态硬件开发落地
如何读取 resources 目录下的文件路径?
三分建设,七分管理!产品、系统、组织三管齐下节能降耗
docker+网桥+redis主从+哨兵模式
【Playwright测试教程】5分钟上手
ingress 待完善
逻辑漏洞----其他类型
How many ways do you know about communication between multiple threads?
Basic form validation process
sqoop ETL tool
一文看懂推荐系统:召回05:矩阵补充、最近邻查找,工业界基本不用了,但是有助于理解双塔模型
Power button (LeetCode) 215. The first K largest elements in the array (2022.08.03)
STM8S105k4t6c---------------Light up LED
一个属于程序员的七夕节!