Fuhui

IO Model


这里使用udp举例,因为udp状态简单:要么收到数据,要么没有收到;tcp协议相对比较复杂

五种I/O模型

两个阶段

两个缓冲区

同步与异步

描述的是用户线程与内核的交互方式

阻塞与非阻塞

描述是用户线程调用内核I/O操作的方式,

系统调用

指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。当你的代码需要做I/O操作(open、read、write)、或者是进行内存操作、甚至是说要获取一个系统时间,就需要通过系统调用来和内核进行交互 系统调用(system call),指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。系统调用提供用户程序与操作系统之间的接口。大多数系统交互式操作需求在内核态运行。如设备IO操作或者进程间通信

阻塞I/O

两个阶段,全程阻塞

见下图,最流行的模型。应用进程调用recvfrom(一次系统调用),然后阻塞,等待两种情况发生:

1. 错误返回
2. 成功返回,数据首先通过网络到达内核缓冲区,然后再拷贝到进程缓冲区,之后返回

系统调用recvfrom成功返回后,应用进程开始处理进程缓冲区里的数据

注意:系统调用不是信号中断,因为系统调用会一直阻塞

非阻塞I/O

第一阶段是非阻塞的,不断检查是否准备好数据;第二阶段阻塞,直到读取数据完成

见下图,recvfrom系统调用调用之后,有两种结果: 轮询检查内核数据,

1. 如果数据还没准备好,内核马上返回给进程,但是会返回一个error,此时进程并没有被阻塞。进程在返回之后,可以干点别的事情,然后再发起recvfrom系统调用。
   重复上面的过程,循环往复的进行recvfrom系统调用。这个过程通常被称之为轮询。
2. 如果数据已经准备好,则阻塞,直到从内核中把数据拷贝到进程结束,然后应用进程开始进行数据处理

特点是用户进程完成巡检

缺点是反复轮询,CPU消耗大;轮询期间进行多次系统调用

![](/img/blog/2019/IO Model-figure_6.2.png#pic_center=300x600)

多路复用

见下图,

I/O多路复用实际上就是用select, poll, epoll监听多个io对象,当io对象有变化(有数据)的时候就通知用户进程。 有些地方也称这种IO方式为事件驱动IO(event driven IO)。 与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。

特点是内核进程完成巡检

缺点是一个进程监视的socket是有限制的,一般是1024个,当然可以修改;而且存在两次系统调用(select和recvfrom)

![](/img/blog/2019/IO Model-figure_6.3.png#pic_center=300x600)

信号

第一阶段构造一个信号处理器,第二阶段阻塞读取数据

![](/img/blog/2019/IO Model-figure_6.4.png)

异步I/O

两个阶段,都是非阻塞的

![](/img/blog/2019/IO Model-figure_6.5.png)

对比

![](/img/blog/2019/IO Model-figure_6.6.png)

参考

  1. https://zhuanlan.zhihu.com/p/54580385
  2. Chapter 6. I/O Multiplexing: The select and poll Functions文章的github地址