Java IO系统总结

参考文章

1. IO相关知识

Java IO系统总结 - 图1
硬件层(Hardware) :
包括与IO相关的CPU、内存、磁盘和网卡;
内核空间(Kernel Space) :
计算机开机首先运行内核程序,内核程序占用的私有空间就是内核空间,并且可支持访问CPU所有指令集(ring0-ring3)以及所有内存空间、IO、硬件设备。
用户空间(User Space) :
每个普通的用户进程的用户空间,只能访问受限的资源,无法直接操作内存、网卡、磁盘等硬件。
用户空间的进程是通过 System Call Interface 这个可以操作底层硬件的API来进行系统调用的,常见的系统调用,如内存映射mmap()、文件操作类的open()、IO读写read()、write();

1.1 四种 IO模型

  1. BIO 同步阻塞
  2. NIO 同步非阻塞
  3. IOM IO多路复用
  4. AIO 异步非阻塞

    1.2 关键字解释

  • 文件描述符
    Linux每打开一个文件都有一个小的整数与之对应。内核利用文件描述符来访问文件,windows里对应叫文件句柄。
  • 缓存IO
    Linux的缓存IO机制中,操作系统会将IO的数据存在文件系统的页缓存(PageCache)中,即数据先拷贝内核缓冲区,然后从缓冲区拷贝到应用的地址空间。
  • IO多路复用(multiplexing)
    原理:通过内核缓冲IO数据的机制,让单进程可以监控多个文件描述符,当某个描述符读就绪或写就绪等,就能通知程序进行相应读写操作。
    优点:这样可以不必创建维护多个进程/线程,大大减小系统开销。

Java IO系统总结 - 图2

  • select机制
    原理:select 函数监视3类文件描述符:writefs、readfds、exceptfds。调用后select会阻塞,直至这有3类描述符就绪,或超时,函数返回。返回后可以遍历fd_set集合来找到就绪的描述符。
    缺点 : 每次调用select需要把fd_set集合从用户态拷贝到内核态。若fs_set集合很大时,系统开销很大,因此fd_set的大小进行限制了,限制为1024。
  • poll机制
    与select机制类似,管理多个描述符也是进行轮询,根据其状态进行处理,poll机制使用的是pollfd结构,使得poll没有最大文件符数量限制。
  • epoll机制
    原理:支持水平触发和边缘触发,最大特点为边缘触发,只告诉一次进程哪些fd刚变为就绪态。epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似回调机制,激活fd,epoll_wait便可收到通知。
    优点:1. 没有描述符个数限制,一个文件描述符管理多个描述符,将文件描述符的事件存放到内核的事件表中,这样在用户空间和内核空间的copy只需一次。 2. epoll是select、poll的增强版,可以显著提高程序在大量并发连接中只有少量活跃的情况下系统CPU利用率,原因是获取事件时,无需遍历整个监听的描述符集,只需遍历被内核IO事件异步唤醒而加入Ready队列的描述符集合。

    2. IO流 抽象类结构

    IO流

    2.1 基于操作字节流的接口

    基于字节的输入输出操作接口分别为:InputStream 和 OutputStream。
    2.1.1 字节输入流

    2.2 基于操作字符流的接口