浅谈5种IO模型的概念

IO的概念

IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。

比如你打开浏览器,访问腾讯首页,浏览器这个程序就需要通过网络IO获取腾讯的网页。浏览器首先会发送数据给腾讯服务器,告诉它我想要首页的HTML,这个动作是往外发数据,叫Output,腾讯服务器把网页发过来,这个动作是从外面接收数据,叫Input。所以,通常,程序完成IO操作会有Input和Output两个数据流。当然也有只用一个的情况,比如,从磁盘读取文件到内存,就只有Input操作,反过来,把数据写到磁盘文件里,就只是一个Output操作。

流是什么?可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。对于浏览网页来说,浏览器和腾讯服务器之间至少需要建立两根水管,才可以既能发数据,又能收数据。

I/O操作是相对于内存而言的,从外部设备进入内存就叫Input,反之从内存输出到外部设备就叫Output.
I/O按照设备来分的话,分为两种,其一是网络I/O,也就是通过网络进行数据的拉取和输出。还有一种是磁盘I/O,主要是对磁盘进行读写工作。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

什么是用户空间和内核空间

虚拟内存被操作系统划分成两块:内核空间和用户空间。
为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响.

内核空间是内核代码运行的地方,
用户空间是用户程序代码运行的地方。

当进程运行在内核空间时就处于内核态,当进程运行在用户空间时就处于用户态。

在这里插入图片描述
Kernel space 可以执行任意命令,调用系统的一切资源
User space 只能执行简单的运算,不能直接调用系统资源必须通过系统调用(又称 system call),才能向内核发出指令

str = "my str" // 用户空间
x = x + 3
file.write(str) // 切换到内核空间
y = x + 42 // 切换回用户空间

在上面的代码中,第一行和第二行都是简单的赋值运算,在 User space 执行。第三行需要写入文件,就要切换到 Kernel space,因为用户不能直接写文件,必须通过内核安排。第四行又是赋值运算,就切换回 User space。

同步、异步的概念

由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。

用烧水的例子来理解:

我们都是通过热水壶来烧水的。在很久之前,科技还没有这么发达的时候,如果我们要烧水,需要把水壶放到火炉上,我们通过观察水壶内的水的沸腾程度来判断水有没有烧开。

随着科技的发展,现在市面上的水壶都有了提醒功能,当我们把水壶插电之后,水壶水烧开之后会通过声音提醒我们水开了。

于烧水这件事儿来说,传统水壶的烧水就是同步的,高科技水壶的烧水就是异步的。

同步请求,A调用B,B的处理是同步的,在处理完之前他不会通知A,只有处理完之后才会明确的通知A。

异步请求,A调用B,B的处理是异步的,B在接到请求后先告诉A我已经接到请求了,然后异步去处理,处理完之后通过回调等方式再通知A。

所以说,同步和异步最大的区别就是被调用方的执行方式和返回时机。同步指的是被调用方做完事情之后再返回,异步指的是被调用方先返回,然后再做事情,做完之后再想办法通知调用方。

什么是阻塞和非阻塞

还是那个烧水的例子,当你把水放到水壶里面,按下开关后,你可以坐在水壶前面,别的事情什么都不做,一直等着水烧好。你还可以先去客厅看电视,等着水开就好了。

对于你来说,坐在水壶前面等就是阻塞的,去客厅看电视等着水开就是非阻塞的。

阻塞请求,A调用B,A一直等着B的返回,别的事情什么也不干。

非阻塞请求,A调用B,A不用一直等着B的返回,先去忙别的事情了。

所以说,阻塞和非阻塞最大的区别就是在被调用方返回结果之前的这段时间内,调用方是否一直等待。=阻塞指的是调用方一直等待别的事情什么都不做。非阻塞指的是调用方先去忙别的事情

5种IO模型详解

在这里插入图片描述

阻塞IO模型

当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。

在这里插入图片描述
在这里插入图片描述

非阻塞IO模型

在这里插入图片描述 在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU。

在这里插入图片描述

IO复用模型

在这里插入图片描述在这里插入图片描述

select ,poll,epoll的区别

在这里插入图片描述在这里插入图片描述
poll方案
在nginx中的使用方法,
在这里插入图片描述poll不知道后端的数据是谁的,但是它会帮我们监听,因此,多次询问十分耗费时间

信号驱动IO模型

在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用IO读写操作来进行实际的IO请求操作。这个一般用于UDP中,对TCP套接口几乎是没用的,原因是该信号产生得过于频繁,并且该信号的出现并没有告诉我们发生了什么事情
在这里插入图片描述
在这里插入图片描述

全异步IO模型

在这里插入图片描述在这里插入图片描述
注意:
此模型和前面模型最大的区别是,前4个都是阻塞的,因为需要自己把用户准备好的数据,放在我的用户空间,而全异步都帮我们做好了。
用户线程完全不需要关心实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。

它是最理想的模型

5种IO模型的区别

在这里插入图片描述

发布了264 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45649763/article/details/104499606