IO详解

95 阅读3分钟

什么是IO? 什么是同步/异步IO? 什么是阻塞/非阻塞IO? 什么是IO多路复用? select/epoll跟IO模型有什么关系? 有几种经典的IO模型呢? BIO、NIO、AIO有什么区别呢?

操作系统的一次IO过程

应用程序发起的一次IO操作包含两个阶段:

  • IO调用:应用程序进程向操作系统内核发起调用。
  • IO执行:操作系统内核完成IO操作。

操作系统内核完成IO操作还包括两个过程:

  • 准备数据阶段:内核等待I/O设备准备好数据
  • 拷贝数据阶段:将数据从内核缓冲区拷贝到用户进程缓冲区

一个完整的IO过程包括以下几个步骤:

  • 应用程序进程向操作系统发起IO调用请求
  • 操作系统准备数据,把IO外部设备的数据,加载到内核缓冲区
  • 操作系统拷贝数据,即将内核缓冲区的数据,拷贝到用户进程缓冲区

image.png

阻塞IO

如果内核数据还没准备好的话,那么应用程序就一直阻塞等待,等待数据从内核拷贝到用户空间,才返回成功。

image.png 缺点:如果内核数据没准备好,用户进程将一直阻塞住,浪费性能。

非阻塞IO模型NIO

如果内核数据没有准备好,先返回错误信息给用户进程,让它通过轮训的方式来询问。

image.png

缺点:依然存在问题,需要不断的来轮训,同样消耗大量的CPU。可以使用IO复用模型,去解决这个问题。

IO多路复用模型

等到内核数据准备好了,主动通知应用进程再去进行系统调用。 系统提供了一些列的函数(select,poll,epoll),可以同时监控多个fd(文件描述)操作,任何一个返回内核数据就绪,应用进程再发起系统调用。

IO多路复用之select

应用进程通过调用select函数,可以同时监控多个fd,在select函数监控的fd中,只要有任何一个数据状态准备就绪了,select函数就会返回可读状态,这时应用进程再发起recvfrom请求去读取数据。

image.png 特点:只需要一次询问即可,大大优化了性能。 缺点: 1 监听的IO的最大连接数有限,linux一般是1024个。 2 select函数返回后,是通过遍历fdset,找到就绪的描述符fd

poll解决了连接数限制问题,但是其他问题依然存在,客户端连接增加,效率也会线性下降。 因此,经典的多路复用模型epoll出现。

IO模型之信号驱动模型

信号驱动IO不再用主动询问的方式去确认数据是否就绪,而是向内核发送一个信号(调用sigaction的时候建立一个SIGIO的信号),然后应用用户进程可以去做别的事,不用阻塞。当内核数据准备好后,再通过SIGIO信号通知应用进程,数据准备好后的可读状态。应用用户进程收到信号之后,立即调用recvfrom,去读取数据。 image.png

异步IO AIO

BIO,NIO,信号驱动,都有一个缺点,等数据准备好后,从内核空间拷贝到用户空间的时候,用户进程是阻塞的。

image.png