目录
5种io模型
io引入
io的本质
以read ,write为例:
- 如果底层缓冲区没有数据/缓冲区已满,会阻塞等待
- 网络更是如此,大部分时间都在等待,直到有数据才进行拷贝
所以,io=等待+拷贝
- 因为上层察觉不到等待的时间,只能将等待时间也纳入io时间,无论是在等数据输入/处理数据好腾出空间,都是在等
- 其实概括一下,等的过程就是在判断条件成立 -- 条件 : 读写事件就绪
并且,在应用层使用这两个函数,本质上是将数据在用户层和os之间传递
- 用户层缓冲区的数据 <---> 系统级缓冲区
- 也就是我们之前提到的,它们本质上都是拷贝函数
io效率的本质
根据上面的内容,我们可以推出:
- 因为高效io = 单位时间内可以拷贝更多的数据
- 又因为拷贝工作是os做的,我们无法改变,且io=等待+拷贝
- 所以,本质上提高io效率,就是要减少等待时间,几乎所有提高io效率的策略,都是在减少等待比重
- 就像,我们为什么要写多线程来代替单进程, 就是因为可以把等待时间从串行->并行
模型引入
以钓鱼为例
假如a来河边钓鱼
- 他是一个会一直关注鱼漂的人,所以在鱼咬钩之前,会一直等待,不会被外界因素打扰
- 对应io模型中的阻塞式io,我们之前接触到的大部分接口都是这样
过了一会又来了个b
- 他和a不一样,他闲不住,没法一直看着鱼漂,他会每隔五分钟查看一下情况,其余时间都在忙自己的(玩手机啦,看书啦等等)
- 对应非阻塞式io(这里是轮询方式)
然后又来了个c
- 他在鱼钩那里挂了一个铃铛,抛竿后就不管了,直到听到铃铛响才去查看
- 对应信号驱动式io,有数据了再来通知他
富豪d也过来钓鱼
- 他和前三个人都不一样,他开着车过来,装着一车鱼竿,然后依次把鱼竿插在地上,全部抛竿后以遍历的方式周期性检查所有鱼漂情况 -- 多路复用/转接
目前来说,d的钓鱼效率是最高的
- 因为鱼竿数量增多,相当于增加了鱼咬钩的概率
- 假设鱼咬任何一个鱼钩的概率是百分之一,那么d钓上鱼的概率就是n*1%,其他人都是1%
最后,大公司老板e也来钓鱼
- 他是带着一个司机坐车过来的,他也想去钓鱼,但一会公司还有事,所以他让司机在这里钓,给他留下钓鱼工具,水桶,手机,如果钓的鱼把桶装满了就用手机通知他
- 小王怎么钓鱼的不重要,重要的是e并没有实际参与钓鱼过程,e只是钓鱼行为的发起者,他只关心数据
- 对应异步io -- 小王就是os,e就是发起io操作的实体(进程/线程)
例子介绍完了,接下来聊聊细节
效率最高的方式
五种io模型中,第四种io效率最高
- 虽然第五种自己不用参与,其实io效率没区别
- 并且异步io写出来的服务逻辑比较混乱一些
所以,多路转接的io方式是我们最值得学习的,也是效率最高的
异步io和同步io的区别
前四个人都属于同步io
- 他们无论如何处理等待时间,总之都亲身参与了等待/钓的过程
最后一个则是完全没有参与
- 只是发起io,最后拿到结果就行
这就是异步/同步的本质区别,在于是否参与io
阻塞式和非阻塞式io的区别
也就是a和b的区别
- 实际上两者的io效率没有区别
- 因为io=等+拷贝,两者都没有改变等待时间的占比,只是等待的方式不同
- 只不过b总体效率高,因为b在等待之余还做了其他事情
介绍
阻塞式io
非阻塞式io
信号驱动式io
多路转接/复用
异步io