定义

I/O(英语:Input/Output),即输入/输出,通常指数据在存储器(内部和外部)或其他周边设备之间的输入和输出,是信息处理系统(例如计算机)与外部世界(可能是人类或另一信息处理系统)之间的通信。输入是系统接收的信号或数据,输出则是从其发送的信号或数据。

冯•诺伊曼计算机的基本思想中有提到计算机硬件组成应为五大部分:控制器,运算器,存储器,输入和输出。这里的输入和输出就指IO。

输入设备

  • 键盘
  • 定点设备
  • 指点杆
  • 鼠标
  • 触控板
  • 轨迹球
  • 扫描仪
  • 麦克风
  • 相机

输出设备

  • 屏幕、投影机
  • 打印机、
  • 扬声器、耳机
  • 闪光灯

双向设备

  • 存储设备,如RAM
  • 一部分USB和火线设备
  • 触摸屏
  • 刻录机
  • ADSL
  • ATM
  • USB

应用程序角度分析

换句话说应用程序发起的一次IO操作实际包含两个阶段:

  1. IO调用阶段:应用程序进程向内核发起系统调用
  2. IO执行阶段:内核执行IO操作并返回

    a. 准备数据阶段:内核等待I/O设备准备好数据

    b. 拷贝数据阶段:将数据从内核缓冲区拷贝到用户空间缓冲区

IO-1

内核空间角度图示

IO-2

应用程序中进程在发起IO调用后至内核执行IO操作返回结果之前,若发起系统调用的线程一直处于等待状态,则此次IO操作为阻塞IO。阻塞IO简称BIO,Blocking IO。

BIO带来了一个问题:如果内核数据需要耗时很久才能准备好,那么用户进程将被阻塞,浪费性能。

那解决方案自然也容易想到,将阻塞变为非阻塞,那就是用户进程在发起系统调用时指定为非阻塞,内核接收到请求后,就会立即返回,然后用户进程通过轮询的方式来拉取处理结果。非阻塞IO简称NIO,Non-Blocking IO。 IO-3

NIO带来了一个问题:就是频繁轮询导致的无效系统调用。

解决NIO的思路就是降解无效的系统调用。

  • IO多路复用之select/poll

select是内核提供的系统调用,它支持一次查询多个系统调用的可用状态,当任意一个结果状态可用时就会返回,用户进程再发起一次系统调用进行数据读取。换句话说,就是NIO中N次的系统调用,借助select,只需要发起一次系统调用就够了。

IO-4

select/poll 虽然解决了NIO重复无效系统调用用的问题,但同时又引入了新的问题。问题是:

  1. 用户空间和内核空间之间,大量的数据拷贝
  2. 内核循环遍历IO状态,浪费CPU时间。

针对select/poll引入的问题,我们把解决问题的思路转回到内核上,如何减少内核重复无效的循环遍历呢?变主动为被动,基于事件驱动来实现。

IO-6

epoll,已经大大优化了IO的执行效率,但在IO执行的第一阶段:数据准备阶段都还是被阻塞的。所以这是一个可以继续优化的点。

异步IO真正实现了IO全流程的非阻塞。用户进程发出系统调用后立即返回,内核等待数据准备完成,然后将数据拷贝到用户进程缓冲区,然后发送信号告诉用户进程IO操作执行完毕。 IO-5

所以,之所以称为异步IO,取决于IO执行的第二阶段是否阻塞。因此前面讲的BIO,NIO均为同步IO。

参考

  • https://zh.wikipedia.org/wiki/I/O

JY