文章目录
什么是IO
IO在计算机中指Input/Output
,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU
这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO
接口。
比如打开一个浏览器,访问百度首页,浏览器这个程序就需要通过网络IO获取百度的网页。浏览器首先会发送数据给百度的服务器,告诉它我想要百度首页的HTML,这个动作是浏览器往外发数据,叫Output
,随后百度服务器把网页发过来,这个动作是浏览器从外面接收数据,叫Input
。所以,通常,程序完成IO
操作会有Input
和Output
两个数据流。当然也有只用一个的情况,比如,从磁盘读取文件到内存,就只有Input
操作,反过来,把数据写到磁盘文件里,就只是一个Output
操作。
IO
编程中,Stream
(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。
Input Stream
就是数据从外面(磁盘、网络)流进内存,Output Stream
就是数据从内存流到外面去。
对于浏览网页来说,浏览器和百度服务器之间至少需要建立两根水管,才可以既能发数据,又能收数据(因为单向流动)。
首先IO的几个经典的模型分为阻塞IO
, 非阻塞IO
, 信号驱动IO
, 异步IO
, 多路转接IO
,我们一一介绍
1.阻塞IO
1.1 定义
在发起IO调用后,如果IO条件不满足则一直等待,直到条件符合
1.2 举例
例如我想要去食堂买个汉堡,但是卖汉堡的老板说,汉堡需要等待5分钟才好,阻塞IO的做法就是我就在汉堡窗口等待5分钟,直到他把汉堡交给我,我才离开
1.3 图解
2.非阻塞IO
2.1 定义
在发起IO调用后,如果条件不满足则直接报错返回,执行其他的指令,然后再次发起IO调用,如果条件不满足继续报错返回,直到调用时发现条件满足,之后执行数据拷贝,然后调用返回
2.2 举例
举个例子,我现在饿了,我还是要去食堂买一个汉堡,汉堡老板仍是告诉我,汉堡需要等一会才能好,于是我没有一直在食堂等待,我去取了个快递,然后又跑回去问汉堡老板,汉堡好没好,老板和我说还没好,然后我又去操场跑了个步,之后又回到食堂,问老板汉堡好没好,老板说汉堡好了,之后我拿着汉堡走了
2.3 图解
阻塞IO和非阻塞IO的区别就在于,发起一个IO调用后,是直接返回,还是等待结果返回
3.信号驱动IO
3.1 定义
自定义IO信号,如果IO条件具备则发送IO信号,收到信号后则打断其他操作进行信号处理,执行IO操作进行数据拷贝,结束后调用返回
3.2 图解
4.异步IO
4.1 理解
CPU
的速度远远快于磁盘、网络等IO。在一个线程中,CPU
执行代码的速度极快,然而,一旦遇到IO操作,如读写文件、发送网络数据时,就需要等待IO操作完成,才能继续进行下一步操作。这种情况称为同步IO。
在IO操作的过程中,当前线程被挂起,而其他需要CPU
执行的代码就无法被当前线程执行了。
因为一个IO操作就阻塞了当前线程,导致其他代码无法执行,所以我们必须使用多线程或者多进程来并发执行代码,为多个用户服务。每个用户都会分配一个线程,如果遇到IO导致线程被挂起,其他用户的线程不受影响。
多线程和多进程的模型虽然解决了并发问题,但是系统不能无上限地增加线程。由于系统切换线程的开销也很大,所以,一旦线程数量过多,CPU
的时间就花在线程切换上了,真正运行代码的时间就少了,结果导致性能严重下降。
由于我们要解决的问题是CPU
高速执行能力和IO设备的慢速严重不匹配,多线程和多进程只是解决这一问题的一种方法。
另一种解决IO问题的方法是异步IO。当代码需要执行一个耗时的IO操作时,它只发出IO指令,并不等待IO结果,然后就去执行其他代码了。一段时间后,当IO返回结果时,再通知CPU
进行处理。
同步和异步的区别就在于是否等待IO执行的结果。
4.2 举例
我现在又饿了,我还是要去食堂买一个汉堡,汉堡老板仍是告诉我,汉堡需要等一会才能好,于是我没有一直在食堂等待,我去取了个快递,然后我又去操场跑了个步,之后又去玩了一会,老板打电话给我说汉堡好了,我才去拿汉堡
很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂,异步IO的复杂度远远高于同步IO。
5.多路IO复用
5.1作用
可以监控多个文件描述符,当文件描述符当中有事件产生的时候,就会通知调用者
5.2 分类
1.select
2.poll
3.epoll
具体我们下次详解