网络IO中的同步/异步&阻塞/非阻塞

作者: shad0w_walker(admin) 分类: 基础知识 发布时间: 2017-03-15 20:33 ė 6 没有评论

//上次面试时候被问了网络相关的东西,一问三不知真的是十分的尴尬赶快补点知识。借鉴了网上很多博客,图片也来自网络。

 

一、同步/异步&阻塞/非阻塞

网络编程中同步、异步、阻塞、非阻塞的概念经常被提及,先说一下这些概念的含义:

同步——在进行调用时,如果没有得到调用结果,就不返回

异步——在进行调用时,不需要立即得到调用结果,当其他部件完成调用结果后,通知调用者获取结果。

阻塞——在进行调用时,如果得不到调用结果,当前线程会被挂起,进入阻塞状态,也就是不再继续执行,直到得到结果才返回。

非阻塞——在进行调用时,如果得不到结果,线程不会阻塞,直接返回结果

 

二、IO以及上述过程具体的区别

一次IO操作的过程是这样的:应用程序触发IO操作,进行系统调用——内核等待数据可读——内核完成IO(将数据从内核拷贝到进程中)——通知应用程序IO完成。对IO而言可以这样理解:

同步和异步是针对应用程序与内核交互而言的。同步IO操作得不到结果就会等待或者轮询去查看IO操作是否完成,直到得到数据才会返回;异步IO操作向内核提交IO请求,然后直接返回,做自己的事情,内核完成IO后再通知进程。二者的区别其实也是阻塞。

阻塞和非阻塞是针对调用得不到结果后的反应而言的。阻塞调用不返回,阻塞线程并等待结果;非阻塞调用立即返回,通知应用程序调用没有的到结果。可以理解为函数实现过程中两种不同的设计。

同步和阻塞都会等待结果,但实际上是有些不同的,阻塞调用会把线程阻塞,但同步调用在等待结果时当前线程还是激活的,只是逻辑上没有当前执行的函数。

 

三、IO模型

Linux下一共有五种IO模型,分别是:

1)阻塞I/O(blocking I/O)

2)非阻塞I/O (nonblocking I/O)

3) I/O复用(select 和poll) (I/O multiplexing)

4)信号驱动I/O (signal driven I/O (SIGIO))

5)异步I/O (asynchronous I/O (the POSIX aio_functions))

阻塞IO

用户进程调用了recvfrom这个系统调用,内核就开始准备数据,在网络中,这是数据并没有到达,内核就要等待数据,这段过程中,进程被阻塞。当内核获得足够的数据,将数据拷贝到用户内存,就可以给用户进程返回结果,然后用户进程解除阻塞状态,继续运行。阻塞IO可以理解为进程发起IO并等待直到准备好数据。

 

非阻塞IO

用户进程进行IO调用时,内核没有准备好数据,这时进程不会阻塞,而是返回一个error,表示没有得到调用的数据。用户进程得到了error的结果,知道数据还没有准备好,就可以进行其他的操作,过段时间再进行系统调用。一旦内核准备好了数据又收到应用程序的IO调用,就将数据拷贝到用户内存,并给用户进程返回结果。非阻塞IO可以理解为进程不断询问内核是否准备好数据。

 

 

IO复用

IO复用主要是select和epoll,与阻塞IO类似,这些函数会使进程阻塞,但是能够对多个进程的IO操作进行阻塞,select和epoll会不断轮询所有IO端口,当有一个IO数据准备好,就会通知对应的进程。

 

信号驱动IO

IO操作进行两次调用,第一次进行关于信号的调用,期间进程可以继续执行,数据准备好之后再次调用,将数据拷贝到用户内存,期间进程阻塞。

 

异步IO

用户进程发起IO操作后会立即返回,可以做其他的事,而内核在得到IO请求后,会开始准备进程所需要的数据并将数据拷贝到用户内存,当这一切完成后,内核会给用户进程发送一个信号,通知进程数据已经准备好。异步IO本质上是进行一次IO调用,然后把IO交给内核,等着内核通知就行了。

 

所有IO模型对比

在这张图中就可以明显看到非阻塞IO和异步IO的区别了

本文出自shad0w_walker,转载时请注明出处及相应链接。

本文永久链接: https://www.sdwalker.com/archives/656.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

返回顶部