IO——同步、异步、阻塞、非阻塞

IO类型

一般情况下:IO又五种类型
BlockingIO: 阻塞型的IO
NonBlockingIO:非阻塞型的IO
IO multiplexing : IO多路服用
signal driven IO:信号量驱动IO
asynchronous IO:异步 IO

但是 signal driven IO 一般不常见,所以一般情况下我们只用四种IO。

IO分类介绍

Blocking IO——阻塞型的IO

在默认的情况下,Linux所有的Socket都是Blocking的,一个典型的读操作流程大概是这样:
在这里插入图片描述
从图中可以看出,用户进程调用了 recvfrom 接收数据的系统调用,整个过程分以下几步:

  1. 用户应用调用 recvfrom 系统调用
  2. kernel 查看有木有准备好的数据,如果木有,那么阻塞等待数据准备好。
  3. 有数据后,把内核内存的 数据拷贝到 用户内存 中,这个拷贝过程也是阻塞的。
  4. 拷贝完成之后,内核返回用户 拷贝完了,这个时候用户进程才开始处理数据。

特点: 对于用户进程来说,不管是 等待数据准备好 还是 数据拷贝 这两个过程,用户进程一直是被阻塞的。

NonBlocking IO——非阻塞的IO

在这里插入图片描述

非阻塞的IO流程如下:

  1. 当用户进程发出 recvfrom 操作时,如果 kernel 中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个 Error。
  2. 用户进程角度接收到 Error ,它发起一个 recvfrom 操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个 Error时 ,它就知道数据还没有准备好,先坐一会儿其他的时,等一会儿发一个 recvfrom 操作。
  3. 若用户端接收的不是OK,那么继续重复步骤2,如果时return OK ,那么用户就等待数据从内核内存拷贝到用户内存。
  4. 拷贝完了就进行数据处理

特点:用户进程其实是需要不断的主动询问kernel数据好了没有。

IO multiplexing : IO多路服用

实际上 IO multiplexing 就是我们经常说的select/poll,poll的意思时轮询。也有的地方成为这样的IO是
event driven IO(事件驱动IO),select/poll的好处就是单个线程的process就能处理多个网络请求,它的基本原理就是select/poll方法会不断的轮询所负责的socket,当某一个socket有数据到达了,就通知用户进程。
在这里插入图片描述
步骤:

  1. 用户调用select,用户的整个进程被block,等待内核监听select负责的socket中有数据返回。
  2. 当有任意一个socket数据准备好了,select就返回,阻塞等待数据从内核内存复制到用户内存。
  3. 复制完处理数据

是不是感觉这个和阻塞的IO很像,是的,的确是很像,但是select/poll的特点就是同时处理多个链接。
多路复用的IO和阻塞的IO 比,多路复用的IO有两个系统调用,select 和 recvfrom,而阻塞的IO只有一个系统调用 recvfrom。

事实上,如果用户链接不多的话,阻塞的IO的服务器性能可能更好一些。多路复用延迟还更大。

Asynchronous I/O——异步IO

在这里插入图片描述
具体步骤:

  1. 用户进程发器read 读操作之后,kernel返回 立刻就可以开始去做其他的事。不阻塞
  2. kernel完成数据准备操作,完成后给进程发一个指定的signal信号.
  3. 用户进程接收到signal信号之后就,处理准备好的数据。

总结

  1. Blocking IO阻塞 和 NonBlocking IO非阻塞的区别是啥?
    答:Blocking IO阻塞: 无论是数据准备还是数据从内核内存拷贝到用户内存,用户进程都是阻塞的。知道对应的进程操作完成
    **NonBlocking IO非阻塞: **数据准备阶段是每隔一段时间去问一下数据有木有准备好,一旦问的返回是OK,才阻塞等待数据从内核内存拷贝到用户内存。

  2. 同步IO和异步IO的区别
    借用国外大佬的几句话:
    A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;
    An asynchronous I/O operation does not cause the requesting process to be blocked;
    这两句话的意思是说,同步IO操作会导致请求进程被阻塞,除非IO操作完成
    异步IO操作不会导致请求的进程被阻塞

这么说的话:
Blocking IO(阻塞)、 NonBlocking IO(非阻塞)、IO multiplexing (多路复用)都是同步IO。
分别说一下原因:
Blocking IO : 这个不要多说了,用户进程是请求的进程,阻塞的IO操作 一直会导致用户进程被阻塞。
这一定是同步IO了
NonBlocking IO: 这个有点理解困难,为什么说非阻塞IO也是同步IO呢?因为定义的 I/O operation(IO操作)是真实的IO操作。上面的图中 recvfrom的时候,如果数据没有准备好,那么这个时候是不会阻塞用户进程的,但是如果数据准备好了,那么就一定会阻塞用户进程,把数据从内核内存往用户进程拷贝。

**IO multiplexing: ** 这个就更不用说了,select等内核返回这段时间用户进程是BLock的,recvfrom 拷贝数据,这一段时间还是Block的。

下面是各个IO的比较图:

在这里插入图片描述
通过文字和图片,相比大家应该有一定的理解了。

最难的就是理解Non Blocking IO 是同步IO了,虽然它绝大部分时间是不会被block的,但是它仍然要求进程去主动check,并且数据准备好以后,也需要recvfrom 来将数据拷贝到用户内存。
而 Asynchronous IO 则完全不同,它就像是用户进程只发送一个命令,然后整个IO过程都是由内核完成的。然后内核给用户进程信号,在此期间,用户进程是不需要主动的去拷贝数据的。

笔者打一个近似的比方:

A,B,C,D 四个开发商,建设楼盘。
A开发商比较笨,开发的楼盘也小,他每天都在工地看开发的怎么样了,直到开发完成(建设 + 收尾),才去启动下一步计划——阻塞IO。
B开发商稍微能力强一些,他不每天在工地,而是隔一段时间去看,直到工程收尾他真正的去手把手指导收尾。
C能力更强,负责多个楼盘的开发,每一个楼盘都进度都不一样,他给每个楼盘设置负责人,那个楼盘进入收尾了,就给他打电话,然后他就去处理收尾。
D是真正的大佬,他直接把手里的楼盘全权承包出去,自己才是楼盘的所有者,承包商 把 建设和收尾都做了,他坐享其成。

参考博文

historyasamirror博主: IO - 同步,异步,阻塞,非阻塞 (亡羊补牢篇).
IBM: 使用异步 I/O 大大提高应用程序的性能.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值