评论

收藏

"异步非阻塞模型" 我觉得还OK!

网络安全 网络安全 发布于:2021-07-05 19:14 | 阅读数:318 | 评论:0

DSC0000.jpeg

  常言道:“温故而知新,可以为师矣”。工作中经常会听到有的同学说“这个我知道!但是我忘了具体咋回事了,我得google查一下”。知识应该在自己脑子中形成一个体系的,有时候我们不能太过依赖google。今天就为大家分享一篇基础知识"网络IO同步与异步、阻塞与非阻塞"的精彩总结,带大家一起来温故知新。
  
  前言
  在网络编程中,阻塞、非阻塞、同步、异步经常被提到。同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?
  
  数据流向
  对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)。当一个read操作发生时,它会经历两个阶段:

  •   等待数据准备 (Waiting for the data to be ready)
  •   将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
  记住这两点很重要,因为这些IO Model的区别就是在两个阶段上各有不同的情况。
  详细过程如下图:
DSC0001.jpeg

  
  网络IO模型详细分析
  常见的IO模型有阻塞、非阻塞、IO多路复用,异步。
DSC0002.png

  以一个生动形象的例子来说明这四个概念:周末我和姑娘逛街,中午饿了,我们准备去吃饭。周末人多,吃饭需要排队,我和姑娘有以下几种方案:
  1
  阻塞
  我和姑娘点完餐后,不知道什么时候能做好,只好坐在餐厅里面等,直到做好,然后吃完才离开。姑娘本想还和我一起逛街的,但是不知道饭能什么时候做好,只好和我一起在餐厅等,而不能去逛街,直到吃完饭才能去逛街,中间等待做饭的时间浪费掉了。这就是典型的阻塞
  网络中IO阻塞如下图所示:
DSC0003.jpeg

  2
  非阻塞
  姑娘不甘心白白在这等,又想去逛商场,又担心饭好了。所以我们逛一会,回来询问服务员饭好了没有,来来回回好多次,饭都还没吃都快累死了啦。这就是非阻塞。需要不断的询问,是否准备好了。
  网络IO非阻塞如下图所示:
DSC0004.jpeg

  3
  多路复用
  与第二个方案差不多,餐厅安装了电子屏幕用来显示点餐的状态,这样我和姑娘逛街一会,回来就不用去询问服务员了,直接看电子屏幕就可以了。这样每个人的餐是否好了,都直接看电子屏幕就可以了,这就是典型的IO多路复用,如select、poll、epoll。
  网络IO具体模型如下图所示:
DSC0005.jpeg

  4
  异步
  姑娘不想逛街,又嫌餐厅太吵了,想好好休息一下。于是我们叫外卖,打个电话点餐,然后我和姑娘可以在家好好休息一下(此处忽略带姑娘回家的细节),饭好了送货员送到家里来。这就是典型的异步,只需要打个电话说一下,然后可以做自己的事情,饭好了就送来了。
  linux提供了AIO库函数实现异步,但是用的很少。目前有很多开源的异步IO库,例如libevent、libev、libuv。
  异步过程如下图所示:
DSC0006.jpeg

  
  同步与异步
  实际上同步与异步是针对应用程序与内核的交互而言的。同步过程中进程触发IO操作并等待或者轮询的去查看IO操作是否完成。异步过程中进程触发IO操作以后,直接返回,做自己的事情,IO交给内核来处理,完成后内核通知进程IO完成。
  同步与异步如下图所示:
DSC0007.jpeg

  
  阻塞与非阻塞
  简单理解为需要做一件事能不能立即得到返回应答,如果不能立即获得返回,需要等待,那就阻塞了,否则就可以理解为非阻塞。
  详细区别如下图所示: DSC0008.jpeg
  
  总结
  通过下面的图片,可以发现非阻塞IO和异步IO的区别还是很明显的:
  在非阻塞IO中,虽然进程大部分时间都不会被block,但是它仍然要求进程去主动的检查,并且当数据准备完成以后,也需要进程主动的再次调用recvfrom来将数据拷贝到用户内存。
  而异步IO则完全不同。它就像是用户进程将整个IO操作交给了他人(kernel)完成,然后他人做完后发信号通知。在此期间,用户进程不需要去检查IO操作的状态,也不需要主动的去拷贝数据。
DSC0009.jpeg

DSC00010.gif


  
关注下面的标签,发现更多相似文章