IO读写的基础原理
我们通常使用I/O调用,并不是直接从物理设备把数据读取到内存或将内存中的数据直接写入到物理设备,而是要通过两层缓冲区(内核缓冲区和用户进程缓冲区)才能实现数据的读写,过程如下图。
IO模型
同步阻塞IO(Blocking IO)
阻塞IO需要内核IO操作彻底完成后,才返回到用户空间执行用户的操作。阻塞指的是用户空间程序的执行状态,传统的IO模型都是同步阻塞IO。
同步非阻塞IO(Non-blocking IO)
非阻塞IO指用户空间的程序不需要等待内核IO操作彻底完成, 可以立即返回用户空间执行用户的操作,即处理非阻塞的状态,与此同时内核会立即返回给用户一个状态值,用户进行通过轮询的方式拉拉取处理结果。
IO多路复用(IO Multiplexing)
在IO多路复用模型中,引入了一种新的系统调用,查下IO的就绪状态。在Linux系统中,对应系统调用为select/epoll系统调用。通过该系统调用,一个进程可以监听多个文件描述符,一旦某个描述符就绪(指内核缓冲区可读/可写),内核能够将就绪的状态返回给应用程序。随后,应用程序根据就绪的状态,进行相应的IO系统调用。
异步IO(Asynchronous IO)
用户空间的线程向内核空间注册了各种IO事件的回调函数,由内核区主动调用。
Java NIO
核心组件
- Channel(通道)
- FileChannel:文件通道,用于文件的数据读写
- SocketChannel:套接字通道,用于Socket套接字TCP连接的数据读写
- ServerSocketChannel:服务器套接字通道(或服务器监听通道),允许监听TCP连接请求,为每个监听到的请求创建一个SocketChannel套接字通道
- DatagramChannel:数据报文通道,用于UDP协议数据读写
- Buffer(缓冲区)
本质上是一个内存块,即可以写入数据,也可以从中读取数据,数据总是从通道读到缓冲区内,或者从缓冲区写入到通道中。
- Selector(选择器)
完成IO的多路复用。一个通道代表一条连接通路,通过选择器可以同时监控多个通道的IO(输入输出)状况。选择器和通道的关系,是监控和被监控的关系。Selector能够选出所监控的通道中准备好的就绪的IO操作事件
参考:
链接
《Netty、Redis、Zookeeper高并发实战》