五种IO模型与阻塞IO

一、前言

        在网络中通信的本质其实是网络中的两台主机的进程间进行通信,而进程通信的本质就是IO。

  • IO分为输入(input)和输出(output)
  • 站在进程的角度讲,进程出去数据为输出,外部数据进入进程为输入
  • 站在内存的角度讲,OS的数据流入硬件为输入,硬件的数据流入OS为输出

通常我们进行IO要使用的recv、send、read、write等函数,他们的工作其实分为两步等+拷贝数据

任何 IO 过程中, 都包含两个步骤. 第一是等待, 第二是拷贝. 而且在实际的应用 场景中, 等待消耗的时间往往都远远高于拷贝的时间. 让 IO 更高效, 最核心的办法就 是让等待的时间尽量少.

二、五种 IO 模型

阻塞 IO:

在内核将数据准备好之前, 系统调用会一直等待. 所有的套接字, 默认都是阻塞方式.

非阻塞 IO:

如果内核还未将数据准备好, 系统调用仍然会直接返回, 并且返回 EWOULDBLOCK 错误码.

非阻塞 IO 往往需要程序员循环的方式反复尝试读写文件描述符, 这个过程称为轮询. 这对 CPU 来说是较大的浪费, 一般只有特定场景下才使用

信号驱动 IO:

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

IO 多路转接:

虽然从流程图上看起来和阻塞 IO 类似. 实际上最核心在于 IO 多 路转接能够同时等待多个文件描述符的就绪状态.

异步 IO:

由内核在数据拷贝完成时, 通知应用程序(而信号驱动是告诉应用程序 何时可以开始拷贝数据).

三、同步通信 vs 异步通信

同步和异步关注的是消息通信机制

  • 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回. 但是一旦调用返回,就得到返回值了; 换句话说,就是由调用者主动等待这个调用的结果;
  • 异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果; 换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果; 而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用.

另外, 我们回忆在讲多进程多线程的时候, 也提到同步和互斥. 这里的同步通信和进程之 间的同步是完全不相干的概念.

  • 进程/线程同步也是进程/线程之间直接的制约关系
  • 是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上协调 他们的工作次序而等待、传递信息所产生的制约关系. 尤其是在访问临界资源的时候.
四、阻塞 vs 非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

  • 阻塞调用是指调用结果返回之前,当前线程会被挂起. 调用线程只有在得到结果之后才会返回.
  • 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程.

非阻塞 IO

C
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

传入的 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).

我们此处只是用第三种功能, 获取/设置文件状态标记, 就可以将一个文件描述符设置为非阻塞.

实现函数 SetNoBlock

基于 fcntl, 我们实现一个 SetNoBlock 函数, 将文件描述符设置为非阻塞.

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>void SetNoBlock(int fd) 
{int fl = fcntl(fd, F_GETFL);if (fl < 0) {perror("fcntl");return;}fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}int main() {SetNoBlock(0);while (1) {char buf[1024] = {0};ssize_t read_size = read(0, buf, sizeof(buf) - 1);if (read_size < 0) {perror("read");sleep(1);continue;}printf("input:%s\n", buf);}return 0;
}
  • 使用 F_GETFL 将当前的文件描述符的属性取出来(这是一个位图).
  • 然后再使用 F_SETFL 将文件描述符设置回去. 设置回去的同时, 加上一个 O_NONBLOCK 参数.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1555770.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

ubunut声卡配置 播放视频没有声音的解决方法 alsamixer和pavucontrol的使用方法

文章目录 &#x1f319;ubuntu22.04网页没有声音&#xff0c;声卡提示Dummy Output&#x1f319;方法一&#xff1a;切换内核&#x1f319;方法二&#xff1a;使用知乎的方法 &#x1f319;ubuntu22.04 连接蓝牙耳机&#xff0c;1秒后断连解决方法ubuntu声音操作alsamixerpavuc…

边缘计算插上AI的翅膀会咋样?

人工智能&#xff08;Artificial Intelligence,AI&#xff09;是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学&#xff0c;是新一轮产业革命的重要驱动力量。2022年底发布的ChatGPT将人工智能技术上升到了一个新的高度。如今&#x…

17岁孩子开发AI应用,4个月入百万,人人都是AI产品经理的时代快来了

随着AI时代的到来叠加经济下行&#xff0c;越来越多的独立开发者梦想着实现年入百万的壮举。 近日&#xff0c;这种小概率事件正在发生。 17岁高中生做了个AI APP&#xff0c;短短四个月销售额达100 万美元。 小伙儿Zach Yadegari&#xff08;下面暂称小扎克&#xff09;在X…

用IMX6UL开发板编写按键输入实验

在之前我们都是讲解如何使用IMX6UL的GPIO输出控制等功能&#xff0c;IMX6U的IO不仅能作为输出&#xff0c;而且也可以作为输入&#xff0c;而我们开发板上具有一个按键&#xff0c;按键肯定是连接了一个IO口的额&#xff0c;我们在这一节将会把IO配置成输入功能&#xff0c;读取…

codetop标签动态规划大全C++讲解(三)!!动态规划刷穿地心!!学吐了家人们o(╥﹏╥)o

每天复习一篇&#xff0c;只有十题左右 1.买卖股票的最佳时机2.买卖股票的最佳时机含手续费3.买卖股票的最佳时机III4.买卖股票的最佳时机IV5.打家劫舍6.打家劫舍II7.不同路径8.不同路径II9.最小路径和10.三角形的最小路径和11.两个字符串的删除操作12.编辑距离13.一和零 1.买卖…

强化学习笔记之【DDPG算法】

强化学习笔记之【DDPG算法】 文章目录 强化学习笔记之【DDPG算法】前言&#xff1a;原论文伪代码DDPG算法DDPG 中的四个网络代码核心更新公式 前言&#xff1a; 本文为强化学习笔记第二篇&#xff0c;第一篇讲的是Q-learning和DQN 就是因为DDPG引入了Actor-Critic模型&#x…

Ubuntu22.04 Docker 国内安装最靠谱教程

目前docker在国内安装常存在众所周知的网络问题&#xff0c;如果安装过程如果从官网地址安装以及安装之后从官网要拉取镜像都存在问题。这篇文章主要针对这两个问题总结最靠谱的docker安装教程。 1. docker安装 1.1 系统环境概述 Ubuntu 22.04linux内核版本 6.8&#xff08;…

重学SpringBoot3-集成Redis(四)之Redisson

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;四&#xff09;之Redisson 1. 添加 Redisson 依赖2. 配置 Redisson 客户端3. 使用 Redisson 实现分布式锁4. 调用分布式锁5. 为什…

二进制的神奇操作——拆位法和贡献思想

拆位的引入 我们来思考这么一个问题&#xff0c;如果给你一个数组&#xff0c;让你去求一个数组里面所有连续子串的异或和的和&#xff0c;问你该怎么求&#xff1f; 我们该如何去处理&#xff0c;首先肯定是会想到暴力的思路&#xff0c;第一层循环遍历左端点&#xff0c;第…

SpringBoot在线教育平台:设计与实现的深度解析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

654、最大二叉树

1、题目描述 . - 力扣&#xff08;LeetCode&#xff09; 其实就是给定了一个所谓"最大二叉树"的规则&#xff0c;让我们去构建二叉树。 以 nums [3,2,1,6,0,5] 为例&#xff0c;规则如下&#xff1a; (1)找出其中的最大值6将其作为根节点&#xff0c;6前面的是左子…

程序传入单片机的过程,以Avrdude为例分析

在市场上有各式各样的单片机&#xff0c;例如Arduino&#xff0c;51单片机&#xff0c;STM等。通常&#xff0c;我们都用其对应的IDE软件进行单片机的编程。这些软件既负责将程序代码转写成二进制代码&#xff0c;即机器语言&#xff0c;也负责将该二进制代码导入单片机。与此同…

C++ 算法学习——7.4.1 优化算法——双指针

双指针法&#xff08;Two Pointers&#xff09;是一种常用的算法技巧&#xff0c;通常用于解决数组或链表中的问题。这种技巧通过维护两个指针&#xff0c;通常分别指向数组或链表的不同位置&#xff0c;来协同解决问题。双指针法一般有两种类型&#xff1a;快慢指针和左右指针…

什么是transformer大模型,答案就在这里

Transformer大模型是一种在自然语言处理&#xff08;NLP&#xff09;领域中广泛使用的模型&#xff0c;其详细数据与分析可以从以下几个方面进行阐述&#xff1a; 1. 模型架构 Transformer模型本质上是一个Encoder-Decoder架构。编码组件由多层编码器&#xff08;Encoder&…

(笔记)第三期书生·浦语大模型实战营(十一卷王场)–书生基础岛第3关---浦语提示词工程实践

学员闯关手册&#xff1a;https://aicarrier.feishu.cn/wiki/ZcgkwqteZi9s4ZkYr0Gcayg1n1g?open_in_browsertrue 课程视频&#xff1a;https://www.bilibili.com/video/BV1cU411S7iV/ 课程文档&#xff1a; https://github.com/InternLM/Tutorial/tree/camp3/docs/L1/Prompt 关…

还在“卷”长度?长文本模型真的基于上下文进行回复吗?

近年来&#xff0c;随着长文本模型&#xff08;Long-context Model, LCM&#xff09;技术的突飞猛进&#xff0c;处理长上下文的能力已成为各大语言模型&#xff08;Large Language Model, LLM&#xff09;的核心竞争力&#xff0c;也是各大技术厂商争夺的焦点。截至2023年12月…

RAG再总结之如何使大模型更好使用外部数据:四个不同层级及查询-文档对齐策略

我们来看看RAG进展。《Retrieval Augmented Generation (RAG) and Beyond: A Comprehensive Survey on How to Make your LLMs use External Data More Wisely》(https://arxiv.org/abs/2409.14924)&#xff0c;主要讨论了如何使大型语言模型&#xff08;LLMs&#xff09;更明智…

Redis中BitMap实现签到与统计连续签到功能

服务层代码 //签到Overridepublic Result sign() {//1.获取当前登录的用户Long userId UserHolder.getUser().getId();//获取日期LocalDateTime now LocalDateTime.now();//拼接keyString keySuffix now.format(DateTimeFormatter.ofPattern(":yyyyMM"));String …

实例分割、语义分割和 SAM(Segment Anything Model)

实例分割、语义分割和 SAM&#xff08;Segment Anything Model&#xff09; 都是图像处理中的重要技术&#xff0c;它们的目标是通过分割图像中的不同对象或区域来帮助识别和分析图像&#xff0c;但它们的工作方式和适用场景各有不同。 1. 语义分割&#xff08;Semantic Segme…

一款基于 Java 的可视化 HTTP API 接口快速开发框架,干掉 CRUD,效率爆炸(带私活源码)

平常我们经常需要编写 API&#xff0c;但其实常常只是一些简单的增删改查&#xff0c;写这些代码非常枯燥无趣。 今天给大家带来的是一款基于 Java 的可视化 HTTP API 接口快速开发框架&#xff0c;通过 UI 界面编写接口&#xff0c;无需定义 Controller、Service、Dao 等 Jav…