阻塞IO、非阻塞IO和异步IO

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liuzhixiong_521/article/details/84670466

IO操作构成

  • 步骤一 : 准备数据,将数据从存储介质(例如硬盘、Socket等)加载到内核缓存。
  • 步骤二 : 拷贝数据,将数据从内核缓存拷贝到用户内存。

阻塞IO

在Linux中,默认情况下所有的Socket都是阻塞IO。一个典型的阻塞读IO操作如下图所示:
在这里插入图片描述
当应用进程调用了recvfrom这个系统调用,操作系统内核就开始了IO的第一个阶段 : 准备数据。
对于网络IO来说,很多情况下数据并不能一次性到达 (比如,还没有收到一个完整的UDP包 ),此时操作系统内核需要等待完整的数据到来。
此时,应用进程整个进程会被阻塞。
当操作系统内核数据准备好了,它会将数据从内核缓存中拷贝到应用内存,应用进程才解除阻塞的状态,重新运行。
所以,阻塞IO的特点就是在IO操作的两个阶段准备数据和拷贝数据都被阻塞了。

非阻塞IO

Linux下,可以通过设置Socket使其变为非阻塞IO。一个典型的非阻塞读IO操作如下图所示:
在这里插入图片描述
当应用进程recvfrom这个系统调用,如果操作系统内核中的数据还没有准备好,那么它并不会阻塞应用进程,而是立刻返回一个error。从应用进程角度讲 ,它发起一个read操作后,并不需要阻塞,而是马上就得到了一个结果。当用户进程判断结果为error时,它能够判断数据还没有准备好,于是它可以再次发送read操作。
一旦操作系统内核中的数据准备完成,并且又再次收到了用户进程的read操作,那么它立刻将数据拷贝到了用户内存,然后成功标识。
所以,在非阻塞式IO中,用户进程需要不断的轮询操作系统内核数据是否准备好。

阻塞IO与非阻塞IO区别

阻塞IO : 应用进程在准备数据和拷贝数据两个阶段等待数据。
非阻塞IO : 应用进程在准备数据阶段轮询,在拷贝数据阶段等待数据。

注 : 阻塞IO和非阻塞IO均为同步IO。

异步IO

一个典型的异步读IO操作如下图所示:
在这里插入图片描述
异步IO的读取操作(aio_read)会通知内核进行读取操作并将数据拷贝至进程中,并通知内核进程整个操作全部完成后的回调函数。
读取操作发出后会立刻返回,程序可以进行其它的操作,所有的读取、拷贝工作都由内核完成。
完成以后,内核调用绑定的回调函数来处理数据。

非阻塞IO与异步IO区别

非阻塞IO : 应用进程在准备数据阶段轮询,在拷贝数据阶段等待数据。
异步IO : 应用进程在准备数据和拷贝数据两个阶段均不等待,可以进行其他操作。

猜你喜欢

转载自blog.csdn.net/liuzhixiong_521/article/details/84670466