五种IO模型

同步或异步? 阻塞或非阻塞?

拿小明用水壶烧水举个栗子

同步

小明在烧水, 水壶比较原始, 水烧开了不会通知, 小明需要自己打开盖子看看水是不是烧开了

异步

小明又在烧水, 这次的新水壶水烧开了会发出"滴滴滴"响的功能, 小明将水放入壶里后, 就走开了, 等听到水壶通知了再回来

阻塞

小明的烧水壶很原始, 烧水的时候需要一直摁着开关, 不能干其他的事(即一烧水就要水烧开了才能走)

非阻塞

小明在等待烧水的过程中, 可以边玩手机边等待

关注点不同

同步/异步关注的是消息如何通知

  • 同步: 自己请求

  • 异步: 等待通知

阻塞/非阻塞关注的是等待消息通知时的状态

  • 阻塞: 其他啥事都不能干

  • 非阻塞: 等待通知时可以干别的事

IO模型

IO 即数据的读取或写入操作,通常用户进程中的一个完整IO分为两阶段:用户进程空间 <=> 内核空间、内核空间 <=> 设备空间(磁盘、网络等)

阻塞IO

阻塞IO

进程发起IO系统调用后,进程被阻塞,转到内核空间处理,整个IO处理完毕后返回进程。操作成功则进程获取到数据。

非阻塞IO

非阻塞IO

进程发起IO系统调用后,如果内核缓冲区没有数据,需要到IO设备中读取,进程返回一个错误而不会被阻塞;进程发起IO系统调用后,如果内核缓冲区有数据,内核就会把数据返回进程。

IO多路复用

IO多路复用

多个的进程的IO可以注册到一个复用器(select)上,然后用一个进程调用该select, select会监听所有注册进来的IO. 如果select没有监听的IO在内核缓冲区都没有可读数据,select调用进程会被阻塞;而当任一IO在内核缓冲区中有可数据时,select调用就会返回, 而后select调用进程可以自己或通知另外的进程(注册进程)来再次发起读取IO,读取内核中准备好的数据; 多个进程注册IO后,只有另一个select调用进程被阻塞

信号驱动IO

信号驱动IO

当进程发起一个IO操作,会向内核注册一个信号处理函数,然后进程返回不阻塞;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用IO读取数据。

异步IO

异步IO

当进程发起一个IO操作,进程返回(不阻塞),但也不能返回结果;内核把整个IO处理完后,会通知进程结果。如果IO操作成功则进程直接获取到数据。