深入理解阻塞/非阻塞IO、同步/异步IO的区别

文章目录

      • 【1】同步、异步、阻塞和非阻塞的概念
      • 【2】阻塞IO模型
      • 【3】非阻塞IO模型
      • 【4】IO复用模型
      • 【5】信号驱动IO模型
      • 【6】异步IO模型
      • 【7】各种IO模型的比较

【1】同步、异步、阻塞和非阻塞的概念

同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。
例如:当程序1调用程序2时,程序1停下不动,直到程序2完成回到程序1来,程序1才继续执行下去。

异步:异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者
例如:当程序1调用程序2时,程序1径自继续自己的下一个动作,不受程序2的的影响。

阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。

非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

【2】阻塞IO模型

使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。

例如:贾同学去机场柜台买机票,买到从西安到上海的机票之后才离开。这一过程就可以看成是使用了阻塞IO模型,因为如果没有从西安到上海的机票,他也要等到有有票了才能离开去做别的事情。很显然,这种IO模型是同步的

模型如下图所示:
深入理解阻塞/非阻塞IO、同步/异步IO的区别_第1张图片

【3】非阻塞IO模型

我们使用recvfrom让recvfrom不管有没有获取到数据都返回,如果没有数据那么一段时间后再调用recvfrom看看,如此轮询。

例如:张同学也要买从西安到上海的机票,发现现在没有票,于是乎她离开了,过了一段时间她又来机场看看有没有去上海的机票…在中间离开的这些时间里,张同学离开了机场(回到用户进程空间),可以做她自己的事情。

这就是非阻塞IO模型。但是它只有是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间(等着排队买机票),因此它还是同步IO

模型如下图所示:

深入理解阻塞/非阻塞IO、同步/异步IO的区别_第2张图片

【4】IO复用模型

这里在调用recv前先调用select或者poll,这两个系统调用都可以在内核准备好数据(网络数据到达内核)时告知用户进程,这个时候再调用recv一定是有数据的。因此这一过程中它是阻塞于select或poll,而没有阻塞于recv

有人将非阻塞IO定义成在读写操作时没有阻塞于系统调用的IO操作(不包括数据从内核复制到用户空间时的阻塞,因为这相对于网络IO来说确实很短暂),如果按这样理解,这种IO模型也能称之为非阻塞IO模型,但是按POSIX来看,它也是同步IO,那么也和楼上一样称之为同步非阻塞IO吧。

这种IO模型比较特别,因为它能同时监听多个文件描述符(fd)。

例如:这个时候又有一位王同学来机场买西安到上海的机票,发现有好多柜台,工作人员告诉他这些柜台都没有卖从西安到上海的机票,让王同学留个电话号码,等有票了之后再打电话告诉他,于是他回去等啊等(select/poll调用中),过了好久工作人员打电话告诉他有票了让他来买票,但是不知道是那个柜台卖的是先到上海的机票,需要王同学自己一个一个去找(select/poll的轮询查找就需事件)这时候就需要提出来epoll的高性能了,他会直接告诉王同学具体是哪个柜台卖的是西安到上海的机票,而不需要一个一个查看。

模型如下图所示:

深入理解阻塞/非阻塞IO、同步/异步IO的区别_第3张图片

【5】信号驱动IO模型

我们也可以用信号,让内核在文件描述符准备好之后用信号SIGIO通知我们,我们把这种方法称之为信号驱动IO。

首先我们允许套接字进行信号驱动IO,并通过系统调用sigaction安装一个信号处理程序,这个系统调用立即返回,进程继续工作,因为他是非阻塞的,当数据报准备好时,就为该进程生成一个SIGIO信号,然后我们得到通知后可用通过recvfrom来接收数据了。

模型如下图所示:
深入理解阻塞/非阻塞IO、同步/异步IO的区别_第4张图片

【6】异步IO模型

异步IO是我们让内核启动操作,在所有动作都做完的时候才通知我们,包括接收数据把数据从内核拷贝到我们的用户空间缓冲区。异步IO和前边我们讲的信号驱动IO主要区别在于:信号驱动IO是由内核告诉我们什么时候可以启动一个IO操作,而异步IO是由内核告诉我们什么IO操作时候完成。

模型如下图所示:

深入理解阻塞/非阻塞IO、同步/异步IO的区别_第5张图片我们调用函数aio_read(Posix 异步I/O函数以aio_或lio _开头),给内核传递描述字、缓冲区指针、缓冲区大小(与read相同的三个参数)、文件偏移(与lseek类似),并告诉内核当整个操作完成时如何通知我们。此系统调用立即返回,我们的进程不阻塞于等待I/O操作的完成
在此例子中,我们假设要求内核在操作完成时生成一个信号,此信号直到数据已拷贝到应用缓冲区才产生,这一点是与信号驱动I/O模型不同的。

例如:这个时候又有一位赵同学来机场买西安到上海的机票,工作人员告诉他现在没有卖从西安到上海的机票,让王同学留个电话号码和住址,等有票了之后会帮他买然后给他寄到他们家里,于是他回去等啊等,过了好久工作人员打电话告诉他票已经买好送到他家门口了。
这种模式不需要赵同学跑去机场自己买票,而只需要在家等着票送到自己家里,在这个过程中赵同学没有做任何事,在票买好之后送到他家里之后才会通知他。

【7】各种IO模型的比较

下图给出了上面五种不同I/O模型的比较。它表明:前四种模型的主要区别都在第一阶段,因为前四种模型的第二阶段基本相同:在数据从内核拷贝到调用者的缓冲区时,进程阻塞于recvfrom调用。然而,异步1/O模型处理的两个阶段都不同于前四个模型。

深入理解阻塞/非阻塞IO、同步/异步IO的区别_第6张图片

同步I/O与异步I/O定义:

  • 同步I/O操作引起请求进程阻塞,直到I/O操作完成。
  • 异步I/O操作不引起请求进程阻塞。

根据上述定义,我们的前四个模型—————阻塞I/O模型、非阻塞I/O模型、1/O复用模型和信号驱动I/O模型都是同步I/O模型,因为真正的I/O操作(recvfrom)阻塞进程,只有异步I/O模型与此异步I/O的定义相匹配。

你可能感兴趣的:(计算机网络,网络编程,linux,阻塞与非阻塞IO,同步和异步IO,信号驱动IO,高效的异步非阻塞IO)