IO读写原理
应用程序通过调用操作系统的IO功能来实现IO读写,当读操作的时候,把数据从内核缓冲区复制到进程的缓存区。而写操作,则是把数据从进程缓存区复制到内核缓存区。也就是说应用程序的IO操作,实际上是缓存的复制。
以一次socket请求和响应为例,流程如下:
1、客户端发起请求,操作系统通过网卡读取请求数据。
2、将数据读取到内核缓冲区。
3、服务端程序通过操作系统的read调用,将请求数据从内核缓存区复制到进程缓存区。
4、服务端处理请求,生成响应数据。
5、服务端程序通过操作系统的write调用,将响应数据从进程缓存区写入内核缓存区。
6、操作系统将内核缓存区的数据写入网卡,发送到客户端。
IO模型
定义
阻塞:
阻塞指的是用户空间程序的状态,阻塞就是一直等待。非阻塞就是拿到内核返回的状态值就返回自己空间。
阻塞IO:指的是需要内核IO操作彻底完成后,才返回到用户空间执行用户的操作。
同步:
同步指的是用户空间和内核空间的IO发起方式。
同步IO:指的是用户空间的线程是主动发起IO请求的一方,内核空间是被动接受方。
异步IO:指的是系统内核是主动发起IO请求的一方,用户控件的线程是被动接受方。
同步阻塞IO(Blocking IO)
在java应用程序中,默认创建的所有socket连接的IO操作都是同步阻塞IO。应用程序从开始IO调用开始,就处于阻塞状态,直到系统调用返回。因此,会为每个连接配置一个独立的线程。不适用于高并发场景。
同步非阻塞NIO(Non-blocking IO):
应用程序需要不断的进行IO系统调用,轮询数据是否已经准备好。
指的是用户程序不需要等待内核IO操作彻底完成,可以立即返回程序控件执行用户的操作,与此同时,内核会立即返回给用户一个状态值。因而,在内核数据没有准备好的阶段,会不断的发起IO系统调用。
在NIO模型中,应用程序开始IO调用,如果内核缓冲区没有数据,调用立即返回。如果有数据,即变成阻塞,知道数据从内核缓冲区复制到用户进程缓冲区,系统调用返回成功。
IO多路复用模型(IO Multiplexing)
IO多路复用模型中,引入了一个新的系统调用, 就绪查询,查询IO的就绪状态。它的流程如下:
1、选择器注册。首先将目标连接,提前注册到Selector选择器中。
2、通过选择器的查询方法,查询注册过的所有连接的就绪状态。当任意一个连接数据就绪,即内核缓冲区有数据,就将其加入到就绪的列表中。
IO多路复用模型的优点是,一个选择器查询线程可以同时处理成千上万个连接。Java的NIO技术,就是使用IO多路复用模型。
异步IO模型(Asynchronous IO)
AIO的基本流程是:用户线程通过系统调用,向内核注册某个IO操作,内核在整个IO操作完成后,通知用户程序,用户执行后续的业务操作。
它的特点是在内核等待数据和复制数据的两个阶段,用户线程都是不阻塞的。用户线程需要接受内核的IO操作完成的事件或者注册一个IO操作完成的回调函数。缺点是需要底层内核的支持。
现状
目前,高并发网络应用程序开发,大多采用IO多路复用模型。
网友评论