java nio中首要的一个重点是Buffer缓冲区,可以把它看成一块内存区在java中的抽象。它可以批量传输数据,以提高数据传输的效率。
缓冲区操作:无非就是把数据读进或输出缓冲区。
缓冲区从磁盘读取数据大致流程:用户进程执行一个系统调用(通过调用read()系统调用函数),将控制权交给内核,此时CPU处于内核态,然后内核向磁盘控制器发起读取数据的命令,要求从磁盘读取数据,磁盘控制器把数据从磁盘读入内核缓冲区,这一步是由DMA完成,无需CPU协助。然后内核缓冲区读满了后,内核把数据从内核临时缓冲区拷贝到进程执行read()系统调用时所指定的用户缓冲区。
虚拟内存:现代操作系统都实用虚拟内存,用一个虚假的地址来取代物理地址,这样有两个好处:
- 多个虚拟地址可以指向同一块物理内存
- 虚拟内存空间可以大于实际硬件的物理内存
多个虚拟地址可以指向同一块物理内存,用户空间是不能直接访问硬件磁盘的,这样读取数据的时候都需要从用户态向内核态的转换,以及要完成一次数据从内核空间向用户空间的一次拷贝。但是如果内核空间的虚拟地址和用户空间的虚拟地址都是指向同一块物理地址的时候,这样用户进程就可以直接读取访问从磁盘读取到内核空间的数据了,无需中间拷贝的过程。
虚拟内存空间可以大于实际硬件的物理内存,现代的操作系统可以通过页交换技术,把进程所在的部分内存页换出到磁盘,用来容纳其它进程所需要使用到的内存页数据,这样看起来的内存空间要比实际内存的可用空间大。
文件IO的大致流程:
- 先确定请求数据所在的文件系统页
- 在内核空间分配足够数量的内存页,以确定能容纳文件系统页
- 在内存页和磁盘系文件系统页建立映射关系
- 为每个内存页建立页错误
- 虚拟内存系统俘获页错误,安排页面调入,从磁盘上读取页内容
- 页面调入完成,文件系统就会对原始数据进行解析,取得文件内容和文件属性信息。
内存映射文件:内存映射IO使用文件系统建立从用户空间到可用文件系统内存页之间的虚拟内存映射,这样有几个好处:
- 用户进程把文件数据当做可用内存,所以读取数据的时候无需执行系统调用
- 用户进程触碰到映射内存空间,页错误自动产生,从而将文件数据从磁盘读进内存。如果用户修改了映射内存空间,页会自动标记为脏页,随后刷新到磁盘,完成磁盘数据的同步
- 内存映射文件,避免了数据从内核空间到用户空间的映射
网友评论