IO:网络IO、磁盘IO。IO流就是输入输出,而输入和输出的地方是各式各样的。所有的io说的都是操作系统和应用之间的事
为什么说IO都是针对系统的,因为客户端和服务端, 都是在自己的宿主机子上,向宿主机询问资源,只是这个资源可能是别的机子通过网络发过去的。如果是通过网络发过去的,那么它就是在行宿主机的网卡索要,和另一个服务没关系。
网络io,网卡(磁盘) 到 内核空间 再到 用户空间 进行操作
https://www.cnblogs.com/flashsun/p/14591563.html
四种IO模型
同步、异步:内核是否主动调用
阻塞、非阻塞:应用请求是否得到内核的立刻反应
同步阻塞IO 、 同步非阻塞IO 、 IO多路复用 、 异步IO
同步阻塞IO(Blocking IO)
在linux中的Java进程中,默认情况下所有的socket都是blocking IO。在阻塞式 I/O 模型中,应用程序在从IO系统调用开始,一直到到系统调用返回,这段时间是阻塞的。返回成功后,应用进程开始处理用户空间的缓存数据。
BIO的优点:
程序简单,在阻塞等待数据期间,用户线程挂起。用户线程基本不会占用 CPU 资源。
BIO的缺点:
一般情况下,会为每个连接配套一条独立的线程,或者说一条线程维护一个连接成功的IO流的读写。在并发量小的情况下,这个没有什么问题。但是,当在高并发的场景下,需要大量的线程来维护大量的网络连接,内存、线程切换开销会非常巨大。因此,基本上,BIO模型在高并发场景下是不可用的。
同步非阻塞IO(Non-blocking IO)
在linux系统下,可以通过设置socket使其变为non-blocking。NIO 模型中应用程序在一旦开始IO系统调用,会出现以下两种情况:
(1)在内核缓冲区没有数据的情况下,系统调用会立即返回,返回一个调用失败的信息。
(2)在内核缓冲区有数据的情况下,是阻塞的,直到数据从内核缓冲复制到用户进程缓冲。复制完成后,系统调用返回成功,应用进程开始处理用户空间的缓存数据。IO多路复用(IO Multiplexing)
NIO的优点:每次发起的 IO 系统调用,在内核的等待数据过程中可以立即返回。用户线程不会阻塞,实时性较好。
NIO的缺点:需要不断的重复发起IO系统调用,这种不断的轮询,将会不断地询问内核,这将占用大量的 CPU 时间,系统资源利用率较低。
总之,NIO模型在高并发场景下,也是不可用的。一般 Web 服务器不使用这种 IO 模型。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。java的实际开发中,也不会涉及这种IO模型。
我们把我们应用中所有的io请求都统一存储,利用一个线程去变量,看看那些返回的不是-1,则可执行它的逻辑。这样很想多路复用,但没有解决,在等待资源不能及时返回,cpu空转的问题
java nio说明:Java NIO(New IO) 不是IO模型中的NIO模型,而是另外的一种模型,叫做IO多路复用模型( IO multiplexing )。 将系统中所有io操作(读写 等待注册 连接) 通过一个selector 注册到系统内核上,由它驱动
内核操作说明
IO多路复用
IO多路复用模型的基本原理就是select/epoll系统调用(这是一个阻塞调用),select、poll 会使内核轮询你感兴趣的事件,在准备好了之后,通知你。因此,好处也就显而易见了——通过一次select/epoll系统调用,就查询到到可以读写的一个甚至是成百上千的网络连接。
目前支持IO多路复用的系统调用,有 select,epoll等等。select系统调用,是目前几乎在所有的操作系统上都有支持,具有良好跨平台特性。epoll是在linux 2.6内核中提出的,是select系统调用的linux增强版本。
异步IO(Asynchronous IO)
AIO的基本流程是:用户线程通过系统调用,告知kernel内核启动某个IO操作,用户线程返回。kernel内核在整个IO操作(包括数据准备、数据复制)完成后,通知用户程序,用户执行后续的业务操作。
异步IO模型缺点:
需要完成事件的注册与传递,这里边需要底层操作系统提供大量的支持,去做大量的工作。
目前来说, Windows 系统下通过 IOCP 实现了真正的异步 I/O。但是,就目前的业界形式来说,Windows 系统,很少作为百万级以上或者说高并发应用的服务器操作系统来使用。
而在 Linux 系统下,异步IO模型在2.6版本才引入,目前并不完善。所以,这也是在 Linux 下,实现高并发网络编程时都是以 IO 复用模型模式为主。
客户端和服务端都是注册到selector上,服务端把客户端的channel注册到selector上的