• 作者:老汪软件技巧
  • 发表时间:2024-08-27 10:03
  • 浏览量:

I/O 请求可以分为两个阶段,分别为调用阶段和执行阶段。

为了方便大家理解,可以看一下这张图:

1 同步阻塞 I/O(BIO)

应用进程向内核发起 I/O 请求,发起调用的线程一直等待内核返回结果。

一次完整的 I/O 请求称为BIO(Blocking IO,阻塞 I/O),BIO 在实现异步操作时,一个请求对应一个线程,在此期间,线程不能执行任何其他任务。

假如想提高并发度,只能采用多线程,但是,线程的资源是有限且宝贵的,创建过多的线程会增加线程切换的开销。

适用场景:

2 同步非阻塞 I/O(NIO)

在非阻塞 I/O 模型中,即使数据尚未可用,I/O 操作也会立即返回。应用程序可以在等待 I/O 操作完成的同时执行其他任务。

应用进程向内核发起 I/O 请求后不再会同步等待结果,而是会立即返回,通过轮询的方式获取请求结果。

NIO 相比 BIO 虽然大幅提升了性能,但是轮询过程中大量的系统调用导致上下文切换开销很大。所以,单独使用非阻塞 I/O 时效率并不高,而且随着并发量的提升,非阻塞 I/O 会存在严重的性能浪费。

模型的理解_模型示例_

3 I/O 多路复用

多路复用实现了一个线程处理多个 I/O 句柄的操作。

多路指的是多个数据通道,复用指的是使用一个或多个固定线程来处理每一个 Socket。

select、poll、epoll 都是 I/O 多路复用的具体实现,线程一次 select 调用可以获取内核态中多个数据通道的数据状态。

多路复用解决了同步阻塞 I/O 和同步非阻塞 I/O 的问题,是一种非常高效的 I/O 模型。

4 信号驱动 I/O

信号驱动 I/O 并不常用,它是一种半异步的 I/O 模型。

在使用信号驱动 I/O 时,当数据准备就绪后,内核通过发送一个 SIGIO 信号通知应用进程,应用进程就可以开始读取数据了。

5 异步 I/O

异步 I/O 最重要的一点是从内核缓冲区拷贝数据到用户态缓冲区的过程也是由系统异步完成,应用进程只需要在指定的数组中引用数据即可。

异步 I/O 与信号驱动 I/O 这种半异步模式的主要区别:信号驱动 I/O 由内核通知何时可以开始一个 I/O 操作,而异步 I/O 由内核通知 I/O 操作何时已经完成。