您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

送分来了,华为一面,介绍下五种 IO 模型

时间:2023-02-26 14:25:34  来源:51CTO  作者:飞天小牛肉

所谓 I/O,就是 Input/Output,输入/输出,在操作系统中,输入输出操作其实并不简单

工作在用户态的应用程序想要读取磁盘中的具体文件内容,就需要经过 System Call(系统调用)陷入内核态

因此,在操作系统中,输入输出操作通常都会包括以下两个阶段:

  1. 准备数据:内核缓冲区准备数据,等待其准备好
  2. 数据拷贝:从内核缓冲区向用户缓冲区复制数据

以网络通信即 Socket 上的输入操作为例,对应的第一阶就是等待数据从网络中到达网卡(对于网络 I/O 来说,很多时候数据在一开始还没有到达。比如,还没有收到一个完整的 TCP 包。这个时候内核就要等待足够的数据到来),然后从网卡中将数据拷贝到内核缓冲区,这样,数据就准备就完成了;第二阶段就是把数据从内核缓冲区复制到用户缓冲区。

图片

操作系统系统如何去管理输入和输出,从而获取输入和输出的数据?这就是 I/O 模型。

linux 中有以下五种 I/O 模型:

  • Blocking I/O:阻塞 I/O
  • Non-Blocking I/O:非阻塞 I/O
  • I/O Multiplexing:I/O 多路复用
  • Signal Blocking I/O:信号驱动 I/O
  • Asynchronous I/O:异步 I/O

Blocking I/O

在 Linux 中,默认情况下所有的 Socket 都是 Blocking,它符合人们最常见的思考逻辑。

上面我们介绍了输入输出操作通常都会包括两个阶段,并不是凭空想想,而是对应具体的 I/O 系统调用的,以网络通信为例,Blocking I/O 就对应阻塞的系统调用 recvfrom

第一阶段,准备数据:当用户进程通过系统调用 recvfrom 进行数据读取,操作系统就开始了 I/O 的第一个阶段-准备数据。这个过程需要等待,也就是说数据被拷贝到操作系统内核的缓冲区中是需要一个过程的。而在用户进程这边,整个进程会被阻塞住

解释下 阻塞 的概念:源自操作系统对进程/线程状态的描述概念,其定义为:操作系统把进程/线程从“运行(running)状态” 挂起为 “阻塞(blocked)状态”(又称“等待(wAIting)状态”)。当进程/线程处于阻塞状态,则意味着其处于暂停运行状态,暂时不会被 CPU 调度执行

第二阶段,数据拷贝:当内核一直等到数据准备好了,它就会将数据从内核空间中拷贝到用户空间,然后系统调用 recvfrom 返回结果,用户进程才解除阻塞的状态,重新运行起来

图片

在上述步骤中,用户进程调用 recvfrom,该系统调用直到数据准备好且被复制到用户缓冲区中才返回。

从调用 recvfrom 开始,到它返回数据的整段时间,用户进程都是被阻塞住的!这就是 Blocking I/O 的特点,可以简单记忆为 “IO 执行的两个阶段用户进程都被阻塞住了”

recvfrom 成功返回后,用户进程才开始继续处理。

Non-Blocking I/O

参考《Unix 网络编程:第一卷》,书中是这样描述 Non-Blocking I/O 的:

"进程把一个套接字设置成非阻塞是在通知内核,当所请求的 I/O 操作非得把本进程投入睡眠才能完成时,不要把进程投入睡眠,而是返回一个错误"

意思就是,如果某个用户进程进行系统调用 recvform 尝试获取数据,但这时候数据还没准备好:

  • 如果操作系统把这个进程挂起,那就是 Blocking I/O
  • 如果操作系统选择立即给用户进程返回错误信息,那就是 Non-Blocking I/O

如下图所示:

图片

非阻塞的 recvform​ 系统调用之后,如果数据还没准备好,应用进程不会被阻塞住,recvfrom​ 立即返回一个 EWOULDBLOCK​ 错误。用户进程在收到 recvfrom 调用的返回信息之后,可以干点别的事情,然后再发起 recvform 系统调用。

重复上面的过程,不断地进行 recvform 系统调用。这个过程通常被称之为**轮询 (polling)**。轮询检查内核数据,直到数据准备好,再拷贝数据到用户进程,进行数据处理。

需要注意的是,当 recvfrom 系统调用进行拷贝数据的时候,用户进程同样是被阻塞住的。

因此,Non-Blocking I/O 的特点就是用户进程需要不断的主动询问内核数据准备好了没有,可以简单记忆为 “IO 执行的第一阶段用户进程非阻塞,第二阶段用户进程阻塞”

I/O Multiplexing

由于 Non-Blocking I/O 需要不断主动轮询,轮询会消耗大量的 CPU 时间,而后台可能有多个任务在同时进行,人们就想到了循环查询多个任务的完成状态,只要有任何一个任务完成,就去处理它。这就是 I/O Multiplexing。

I/O Multiplexing 引入了新的系统调用 select/poll/epoll(也成为多路复用器),这几个系统调用也是重点,不过本文就不过多阐述了。

具体来说,I/O Multiplexing 就是将多个应用进程的 Socket 注册到一个多路复用器(select/poll/epoll)上,然后使用一个进程来监听该多路复用器,多路复用器会不断的轮询所有注册进来的 Socket,只要有一个 Socket 的数据准备好,就会返回该 Socket。再由应用进程发起真正的 IO 系统调用(也就是 recvfrom,和 Blocking I/O 一样),来完成数据读取。

简单来说,I/O Multiplexing 就是同时阻塞了多个应用进程,而且可以同时对多个 Socket 进行检测,直到有数据可读或可写时,才真正开始 I/O 操作。

图片

比较上图和 Blocking I/O,你会发现 I/O Multiplexing 的 I/O 操作和 Blocking I/O 似乎差不多,事实上,IO 多路复用还更差一些,因为这里需要使用两个系统调用 (select​ 和 recvfrom​),而 Blocking IO 只需要一个系统调用 (recvfrom)。

但是,IO 多路复用的优势并不是对单个连接能处理得更快,而是只需要一个进程就可以同时处理多个 I/O,能同时处理更多的连接。

Signal Blocking I/O

Signal Blocking I/O 就是当用户进程发起 I/O 操作的时候,首先通过系统调用 sigaction​ 向内核注册一个信号处理函数,这个系统调用会立即返回不会阻塞用户进程;当内核数据准备好了就会发送一个 SIGIO 信号给用户进程,这样用户进程就知道内核数据准备好了,可以开始执行 I/O 系统调用了。

图片

和 Non-Blocking I/O 一样,信号驱动 IO 的用户进程在 I/O 的第一阶段准备数据是非阻塞的,在第二阶段数据拷贝是阻塞的

不过信号驱动 IO 基于回调机制,其实现和开发应用难度大,因此在实际中并不常用。

Asynchronous I/O

异步 I/O,先来解释下什么是异步?

POSIX 的定义如下:

  • 同步 I/O 操作(synchronous I/O operation):导致请求进程阻塞,直到 I/O 操作完成
  • 异步 I/O 操作(asynchronous I/O operation):不导致请求进程阻塞

根据这个定义,我们可以做一个分类了,那就是上述四种 I/O 都是同步 I/O!因为它们无一例外都会在第二阶段阻塞住用户进程直到 I/O 操作完成。

这就是为什么你会看见有人把 “阻塞 I/O” 称之为 “同步 阻塞 I/O”,把 “非阻塞 I/O” 称之为 “同步 非阻塞 I/O” 了

而异步 IO 所谓的在整个 I/O 操作期间都不会阻塞用户进程,其通常的工作机制是:

用户进程告知内核启动某个 I/O 操作,并让内核在整个操作(包括将数据从内核复制到用户缓冲区)完成后通知用户进程。

这与 Signal Blocking I/O 的本质区别就是:

  • Signal Blocking I/O 是在数据准备好了之后进行通知,告知应用进程可以启动 I/O 操作进行拷贝数据了
  • Asynchronous I/O 是在整个 I/O 操作完成了之后进行通知,告知应用进程 I/O 操作已经完成了

下图给出了一个异步调用的例子:

图片

用户进程进行异步系统调用 aio_read​ 之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户进程可以去做别的事情。等到数据准备好了,内核直接拷贝数据给用户进程(不需要用户进程再主动发起 recvfrom 系统调用),拷贝完毕后内核才会给用户进程发送通知,告诉用户进程操作已经完成了。

所以,异步 IO 的两个阶段,用户进程都是非阻塞的,用户进程将整个 IO 操作都交由内核完成,内核完成后会发送通知。在此期间,用户进程不需要去检查 IO 操作的状态,也不需要主动的去拷贝数据。

五种 I/O 模型比较

本文理清了五种 I/O 模型,并区分了阻塞/非阻塞、同步和异步的概念

最后上张图对比下,加深印象

图片



Tags:IO 模型   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
送分来了,华为一面,介绍下五种 IO 模型
所谓 I/O,就是 Input/Output,输入/输出,在操作系统中,输入输出操作其实并不简单工作在用户态的应用程序想要读取磁盘中的具体文件内容,就需要经过 System Call(系统调用)陷入内核态...【详细内容】
2023-02-26  Search: IO 模型  点击:(131)  评论:(0)  加入收藏
▌简易百科推荐
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(0)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(6)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(13)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(9)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(11)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(9)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
站内最新
站内热门
站内头条