UNIX中的五种I/O模型

7416970-31cf423001394697.jpg

在Java网络编程中,应用的较多的主要有BIO,NIO俩种模型,前者为传统的阻塞IO模型,后者为Java1.4后来新加入的非阻塞IO模型,由于后者的性能前者要高出很多,所以开发高性能的应用时,基本都会选择NIO模型。最典型的比如大名鼎鼎的Netty框架就是基于NIO开发的(Netty框架几乎无处不在,)。另外还有一种不太常用的Java1.7中新加入的AIO模型,是NIO的2.0版本,应用较少,与NIO的主要区别在于AIO是基于事件回调的。

所有Java的这些IO模型都是基于底层来实现的,我们先来简单了解下操作系统层面上的IO模型,了解之后会对Java的实现理解有一定的帮助。在Unix网络编程一书中定义了5种I/O模型

阻塞式I/O

这是最简单也是最早出现的I/O模型。来看一下该模型的流程图

7416970-0d9cc56b0c0485df.PNG
源自UNIX网络编程

进行IO操作时,进程调用recvfrom,该函数会一直阻塞直到数据到达或者报错才能返回,从调用recvfrom开始到它返回的整段时间内是被阻塞的。这意味着我们的程序在这段等待的时间内做不了任何事情。

非阻塞I/O

当调用recvfrom没有数据可返回时,内核立即返回一个EWOULDBLOCK错误,直至数据报准备好时,才正常返回。我们可以对它进行轮询,查看是否有数据到来,但是这么做的缺点是比较耗费CPU时间。

7416970-7a70fba4a0e67b21.PNG

I/O复用模型

该模型由select与poll函数支持,这两个函数作用是内核一旦发现进程指定的一个或多个I/O条件就绪时,就会通知进程。

调用select或者poll,使其不阻塞在I/O系统调用上。只阻塞在select或者poll调用,等待数据报套接字变为可读。当套接字返回可读这一条件时,则调用recvfrom把数据读出。该模型的优势在于select可以同时等待多个描述符(一个socket的读写对应一个描述符)就绪。

7416970-4ed730dce1860d37.PNG

信号驱动式I/O

与I/O复用模式区别在于,它可以让内核在描述符就绪时发送SIGIO信号通知我们。这种模型优势在于等待数据报到达期间进程不被阻塞。

7416970-605551d6ef1212aa.PNG

异步I/O模型

进程会告知内核启动某个操作,并让内核在整个操作完成后通知我们,与信号驱动模型区别在于,信号模型通知我们何时可以启动一个I/O操作,异步模型通知我们I/O操作何时完成。在等待I/O完成期间,我们的进程不被阻塞。

7416970-4ae79824fa7315fb.PNG

比较

可以看出异步I/O模型的性能是最佳的,几乎阻塞时间。

7416970-97038908bed313f3.PNG

参考:UNIX网络编程

7416970-ad01269279ce7ee2.gif

猜你喜欢

转载自blog.csdn.net/weixin_34310127/article/details/87144182