IO 同步,异步,阻塞,非阻塞

6 篇文章 1 订阅

参考文章:https://blog.csdn.net/historyasamirror/article/details/5778378

好文推荐:https://blog.csdn.net/lengxiao1993/article/details/78154467

唉最近真是高产似母猪,刚进新公司工作量暂时不饱和,只能每天学学学学学学查漏补缺啦,学习使我快乐哈哈哈哈哈哈哈哈

标题里的词汇相信都经常看到,但是能说清楚的估计20个人里面能有1个就不错了,网上的资料也是五花八门,大部分描述差不多,很多时候估计作者本身也是似懂非懂,我也看了很多文章,抬头的参考是写的最清楚的,这篇文章的博主也曾有过错误的理解,这一篇是纠正篇,果然写得很清晰。

同样的,整理并加上自己的理解写在这里。

什么是IO

I/O就是输入和输出,核心是I/O流,流用于读写设备上的数据,包括硬盘文件、网络等

我们写的代码都是运行在用户进程/线程中的,要读写硬盘或网络数据无法直接操作,而要通过内核,写数据时把数据写到内核,内核再写到硬盘或者通过网络发出去,读数据时,数据也是先到内核,代码再从内核中把数据读到用户线程

总结:IO发生时涉及的对象和步骤。
对于一个网络IO (以read举例),涉及到两个系统对象,一个是调用这个IO的用户进程(或线程),另一个就是系统内核(kernel)。当一个read操作发生时,它会经历两个阶段:
1. 等待数据准备 (Waiting for the data to be ready)
2. 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
记住这两点很重要,因为这些各个IO模型的区别就是在两个阶段上各有不同的情况。


下面分别介绍常见的:

中文英文
阻塞IOBlocking IO
非阻塞IONonBlocking IO
IO多路复用IO Multiplexing
异步IOAsynchronous IO

阻塞 Blocking IO

当用户要读取网络数据时,就开始了第一个阶段:内核准备数据。
对于网络IO来说,很多时候数据在用户调用方法时还没有完全到达(比如,还没有收到一个完整的UDP包),这个时候内核就要等待数据完整到达。用户进程此时会被阻塞。
当内核中数据完整到达了,进入第二阶段,用户进程/线程就会将数据从内核拷贝到用户内存,然后内核返回结果,用户进程才解除block的状态,继续运行。
所以,Blocking IO的特点就是在IO执行的两个阶段都被block了。

非阻塞 Non-Blocking IO

当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的read,那么内核马上就将数据拷贝到用户内存,然后返回结果。
所以,用户进程其实是需要不断的主动询问kernel数据好了没有,也叫轮询IO,特点是第一阶段不阻塞,第二阶段阻塞,并不是完完全全的非阻塞

多路复用 IO Multiplexing

select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll方法会阻塞用户线程,然后内核会不断的轮询所负责的所有socket,一旦发现进程指定的一个或者多个Socket可以读写数据了,它就通知该进程,然后进程读写数据继续运行。
也就是说用户的读写请求会被select方法全部hold住,整个过程还是阻塞的,只是原来是被内核hold住,现在是被select挡住。
好处是原来一个进程/线程只能处理一个连接,那么这个连接阻塞的时间就被浪费了,多路复用把这些时间用来服务别的Connection了。

2019-10-31补充
以下完全个人理解,不确保正确:多路复用最大的好处是减少了线程数,在阻塞和非阻塞IO下,每个网络连接(拿web应用服务器来说)都需要一个线程去盯着它,不管是阻塞等待,还是非阻塞定期轮训。但是多路复用只需要一个线程盯着就好了,就是每过来一个IO读请求或者IO写请求,直接告诉内核我要做这个事情,内核帮这个线程盯着,再来一个再告诉内核,内核继续盯着,内核会去轮训看哪些IO准备好了,然后告诉这个盯着的线程,线程再继续接下去的工作(可能是安排别的线程继续)

异步 Asynchronous IO

从用户进程角度,当它发起read操作之后,立刻就可以开始去做其它的事。
从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。
可以看出内核干了所有事情
原博说linux下的异步IO其实用得很少,我也没想出这种IO要怎么利用起来。


好了,介绍完毕,看到这里细心的小伙伴应该发现了,介绍了阻塞非阻塞异步,那同步IO去哪了,其实同步IO就是代表会阻塞的IO,也就是包含了上面介绍的阻塞非阻塞多路复用三种,感觉要疯了,代表会阻塞的IO,却包含了非阻塞IO,再回过头去看看非阻塞IO的总结部分,它其实不是完完全全的阻塞,而是第一阶段不阻塞,第二阶段阻塞,所以它也属于同步IO,多路复用也是类似。而异步IO一定是非阻塞的,都异步了,本来两个会被阻塞的阶段都被内核做了,而且做好了会通知你,再阻塞有啥意义呢?所以我们不去讨论异步阻塞和非阻塞

完毕,感觉清晰多了,希望不会过段时间发现又有问题(╯‵□′)╯︵┻━┻

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值