JAVA IO之系统IO
基本概念
VFS(Virtual File System):VFS(virtual File System)的作用就是采用标准的Unix系统调用读写位于不同物理介质上的不同文件系统,即为各类文件系统提供了一个统一的操作界面和应用编程接口。VFS是一个可以让open()、read()、write()等系统调用不用关心底层的存储介质和文件系统类型就可以工作的粘合层。
FD(File Descriptor):内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
pageCache:通常4K,是通过将磁盘中的数据缓存到内存中,从而减少磁盘I/O操作,从而提高性能。此外,还要确保在page cache中的数据更改时能够被同步到磁盘上,后者被称为page回写(page writeback)。一个inode对应一个page cache对象,一个page cache对象包含多个物理page。
bufferCache:块缓冲,通常1K,对应于一个磁盘块,用于减少磁盘IO,一个pageCache里通常有多个bufferCache
读写工作流程
磁盘bufferCachepageCache应用程序
系统IO工作流程
网络IO
TCP
tcp:面向连接的,可靠的传输协议-->三次握手-->内核级开辟资源
socket:四元组(唯一标识) cip_cport+sip_sport-->内核级(即便你不accept 也会开辟资源)
面试题:服务端是否需要为client的连接分配一个随机端口号?不需要的,c-s会自己维护四元组通讯携带着四元组能够找到应对的连接。
常用的IO模型
用什么样的通道将数据发送给对方,BIO、NIO 或者 AIO,I/O 模型在很大程度上决定了框架的性能。
阻塞I/O(传统IO-BIO)
总结:
当进程调用recvfrom时,该函数直到①数据报到达且被复制到应用进程缓冲区;②或者发生错误(比如被信号中断)才返回。
所以,阻塞式IO的特点就是在I/O执行的两个阶段都被阻塞了——阻塞等待数据,阻塞拷贝数据。
特点如下:
每个请求都需要独立的线程完成数据 Read,业务处理,数据 Write 的完整操作问题。
当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。
连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费。
非阻塞式I/O
说明:
当对一个非阻塞 socket 执行读操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个EWOULDBLOCK错误;如果内核中有数据准备好了,它会立即将数据拷贝到用户内存,并成功返回。
由于非阻塞I/O在没有数据时会立即返回,故用户进程通常需要循环调用recvfrom,不断地主动询问内核数据是否ready。
所以,非阻塞式IO的特点是在I/O执行的第一个阶段不会阻塞线程,但在第二阶段会阻塞。
I/O复用模型
IO复用(IO multiplexing),也称事件驱动IO(event-driven IO),就是在单个线程里同时监控多个套接字,通过 select 或 poll 轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。
总结:
可以看出,进程阻塞在select调用上,等待有套接字变为可读;当有套接字可读以后,调用recvfrom把数据报从内核复制到用户进程缓冲区,此时进程阻塞在IO执行的第二个阶段。
如上图整个用户进程其实是一直被阻塞的,但IO复用的优势在于可以等待多个描述符就绪。
所以,IO复用的特点是进行了两次系统调用,进程先是阻塞在 select/poll 上,再是阻塞在读操作的第二个阶段上。
信号驱动IO模型
信号驱动式IO(signal-driven IO),就是让内核在描述符就绪时发送SIGIO信号通知用户进程。
总结:
首先需要开启 socket 的信号驱动式IO功能,然后通过sigaction系统调用注册SIGIO信号处理函数 —— 该系统调用会立即返回。当数据准备好时,内核会为该进程产生一个SIGIO信号,这时就可以在信号处理函数中调用 recvfrom 读取数据了。
所以,信号驱动式IO的特点就是在等待数据ready期间进程不被阻塞,当收到信号通知时再阻塞并拷贝数据。
异步IO模型
异步IO(asynchronous IO)其实用得很少,在Linux 2.5 版本的内核中首次出现,在 2.6 版本的内核中才成为标准特性。
总结:
用户进程在发起aio_read操作后,该系统调用立即返回 —— 然后内核会自己等待数据ready,并自动将数据拷贝到用户内存。整个过程完成以后,内核会给用户进程发送一个信号,通知IO操作已完成。
异步IO与信号驱动式IO的主要区别是:信号驱动式IO是由内核通知我们何时启动一个IO操作,而异步IO是由内核通知我们IO操作何时完成。
所以,异步IO的特点是IO执行的两个阶段都由内核去完成,用户进程无需干预,也不会被阻塞。
多路复用IO有几种IO模型
select、poll、epoll 三种模型 一般情况下,我们使用epoll
select、poll 基本是一样的唯一区别是select有最大上线一般1024,poll没有io上线
poll V.S epoll
主要在epoll比poll在内核中多开辟了一块空间来存储有状态的fd的结果集,用户进程直接能使用进行操作,而poll需要去所有FDS中遍历有状态的FD浪费了资源影响了效率。