NOTE

4.2 IO模型

1. 同步 vs 异步 - 应用程序调用系统调用,过程由谁处理 - 前者是我来询问你 同步是由应用程序自己处理 - 后者是你来通知我 异步是由操作系统处理,完成之后通过回调或者事件通知 2. 阻塞 vs 非阻塞 - 应用程序调用系统调用,没有结果怎么办? - 阻塞是应用程序会等待 - 非阻塞是应用程

Operating System / Linux创建于 更新于 historical

这是历史学习笔记,可能存在过时或不完整的理解。

1. 同步 vs 异步

  • 应用程序调用系统调用,过程由谁处理
    • 前者是我来询问你同步是由应用程序自己处理
    • 后者是你来通知我异步是由操作系统处理,完成之后通过回调或者事件通知

2. 阻塞 vs 非阻塞

  • 应用程序调用系统调用,没有结果怎么办?
    • 阻塞是应用程序会等待
    • 非阻塞是应用程序立即返回,然后让应用程序轮询 注意跟是否消耗CPU没关系,磁盘/网络->内核是DMA copy,不消耗CPU,但这个过程对应用来说依然是阻塞的

3. IO模型

  • 如果磁盘或者网络<->内核区以及内核区<->用户区都不是阻塞的,那么是异步IO
  • 如果内核区<->用户区是阻塞的,那么是同步IO
    • 同步IO根据磁盘或者网络<->内核区是否阻塞继续分类
      • 阻塞:
        • 同步阻塞IO
      • 非阻塞:
        • 用户态轮询:同步非阻塞IO
        • 内核态轮询:IO多路复用
        • 由操作系统回调函数:信号驱动
同步阻塞IO 同步非阻塞IO IO多路复用 信号驱动IO 异步IO
内核区<->用户区 阻塞 阻塞 阻塞 阻塞 非阻塞
磁盘或者网络<->内核区 阻塞 非阻塞+应用程序轮询 非阻塞+内核态轮询 非阻塞+回调 非阻塞

3.1. 同步阻塞IO

  • 应用程序调用read、write函数
  • 如果用于网络IO,需要创建多线程服务多个用户,但是线程不可能无限创建

3.2. 同步非阻塞IO

  • 应用程序调用read、write函数+O_NONBLOCK参数
  • 如果用于网络IO,可以由一个线程服务多个用户,但是由于是轮询调用系统调用,那么CPU会在内核态和用户态切换,很耗费CPU

3.3. IO多路复用

  • 应用进程调用select、poll、epoll
  • 如果用于网络IO,可以由一个线程服务多个用户,有IO事件发生会由IO多路复用器通知上层应用处理,而不是由上层应用主动轮询,因此不会造成频繁CPU内核态用户态的切换

3.3.1. Reactor编程模型

事件驱动编程的一种, 网络服务编程的流程是这样的:

  1. accept
  2. read/write socket
  3. decode/encode+serialize/deserialize+logic 单Reactor单线程模型:三个操作都是在一个线程中执行的。比如Redis 单Reactor多线程模型:前两个操作是在一个线程中执行,最后一个操作是通过多线程执行的 多Reactor多线程模型:第一个操作在一个线程执行,第二个操作在CPU核数的线程中执行,最后一个操作通过多线程执行。比如Netty Reactor线程模型 - 知乎 五分钟快速理解 Reactor 模型_朱小厮的博客-CSDN博客

3.4. 信号驱动IO

3.5. 异步IO

  • 应用进程调用Linux的aio或者Windows的IOCP

4. 参考