本文介绍操作系统I/O工作原理,Java I/O设计,基本使用,开源项目中实现高性能I/O常见方法和实现,彻底搞懂高性能I/O之道

基础概念

在介绍I/O原理之前,先重温几个基础概念:

  • (1) 操作系统与内核

操作系统:管理计算机硬件与软件资源的系统软件
内核:操作系统的核心软件,负责管理系统的进程、内存、设备驱动程序、文件和网络系统等等,为应用程序提供对计算机硬件的安全访问服务

  • 2 内核空间和用户空间

为了避免用户进程直接操作内核,保证内核安全,操作系统将内存寻址空间划分为两部分:
内核空间(Kernel-space),供内核程序使用
用户空间(User-space),供用户进程使用
为了安全,内核空间和用户空间是隔离的,即使用户的程序崩溃了,内核也不受影响

  • 3 数据流

计算机中的数据是基于随着时间变换高低电压信号传输的,这些数据信号连续不断,有着固定的传输方向,类似水管中水的流动,因此抽象数据流(I/O流)的概念:指一组有顺序的、有起点和终点的字节集合

抽象出数据流的作用:实现程序逻辑与底层硬件解耦,通过引入数据流作为程序与硬件设备之间的抽象层,面向通用的数据流输入输出接口编程,而不是具体硬件特性,程序和底层硬件可以独立灵活替换和扩展

I/O 工作原理

1 磁盘I/O

典型I/O读写磁盘工作原理如下:

tips: DMA:全称叫直接内存存取(Direct Memory Access),是一种允许外围设备(硬件子系统)直接访问系统主内存的机制。基于 DMA 访问方式,系统主内存与硬件设备的数据传输可以省去CPU 的全程调度

值得注意的是:

  • 读写操作基于系统调用实现
  • 读写操作经过用户缓冲区,内核缓冲区,应用进程并不能直接操作磁盘
  • 应用进程读操作时需阻塞直到读取到数据

2 网络I/O

这里先以最经典的阻塞式I/O模型介绍:

tips:recvfrom,经socket接收数据的函数

值得注意的是:

  • 网络I/O读写操作经过用户缓冲区,Sokcet缓冲区
  • 服务端线程在从调用recvfrom开始到它返回有数据报准备好这段时间是阻塞的,recvfrom返回成功后,线程开始处理数据报

Java I/O设计

1 I/O分类

Java中对数据流进行具体化和实现,关于Java数据流一般关注以下几个点:

  • (1) 流的方向
    从外部到程序,称为输入流;从程序到外部,称为输出流

  • (2) 流的数据单位
    程序以字节作为最小读写数据单元,称为字节流,以字符作为最小读写数据单元,称为字符流

  • (3) 流的功能角色

从/向一个特定的IO设备(如磁盘,网络)或者存储对象(如内存数组)读/写数据的流,称为节点流
对一个已有流进行连接和封装,通过封装后的流来实现数据的读/写功能,称为处理流(或称为过滤流);

2 I/O操作接口

java.io包下有一堆I/O操作类,初学时看了容易搞不懂,其实仔细观察其中还是有规律:
这些I/O操作类都是在继承4个基本抽象流的基础上,要么是节点流,要么是处理流

2.1 四个基本抽象流

java.io包中包含了流式I/O所需要的所有类,java.io包中有四个基本抽象流,分别处理字节流和字符流:

  • InputStream
  • OutputStream
  • Reader
  • Writer

2.2 节点流

节点流I/O类名由节点流类型 + 抽象流类型组成,常见节点类型有:

  • File文件
  • Piped 进程内线程通信管道
  • ByteArray / CharArray (字节数组 / 字符数组)
  • StringBuffer / String (字符串缓冲区 / 字符串)

节点流的创建通常是在构造函数传入数据源,例如:

FileReader reader = new FileReader(new