五种I/O模型

文档地址:https://www.cse.huji.ac.il/course/2004/com1/Exercises/Ex4/I.O.models.pdf

五种I/O模型:

1. blocking I/O 阻塞I/O

2. nonblocking I/O 非阻塞I/O

3. I/O multiplexing (select and poll) I/O多路复用

4. signal driven I/O (SIGIO) 信号驱动I/O

5. asynchronous I/O (the POSIX aio_functions) 异步I/O

对于input操作,有两个不同的阶段:

  1. 等待数据准备完毕(用户空间 通过 内核空间 调用系统资源,数据准备完毕是在内核里的)

  2. 从kernel拷贝数据到相应的进程 (即从 内核空间 复制到 用户空间 的某个进程,内核空间是系统内核运行的地方,用户空间是用户程序运行的地方,两者是独立分割的,用户空间没有什么权限,只能通过内核空间调用系统资源)

对于socket的input,两个阶段通常是:

  1. 等待网络的数据到达,并将数据拷贝到内核空间的buffer里。

  2. 从kernel的buffer里拷贝数据到应用程序的buffer

1. 阻塞I/O

img

上图使用的是UDP协议,在这个过程中,进程调用 recvfrom 来接收数据,在这个过程中,程序一直是阻塞的,直到网络数据报到达本地,并且数据从内核空间拷贝到了用户空间,此时才会 return,当 recvfrom 成功 return 后,应用程序才获取到这个数据报。

从图看出,此模型全程阻塞。

2. 非阻塞I/O

img

首先,进程每隔一阵子调用一次 recvfrom 来接收数据,图中前三次调用 recvfrom,但是数据报没有准备好,所以每一次内核都返回 EWOULDBLOCK 错误,第四次调用 recvfrom,数据报此时已经准备完毕,拷贝到用户空间中后,recvfrom 成功返回,此时进程就获取到了值。

当系统用这种不停的循环的方法对一个非阻塞的描述符调用 recvfrom,这种被称为 polling

此模型并不阻塞,但是需要循环查询,浪费CPU的时间,低效。

3. 多路复用I/O

img

把一个 select 阻塞住,直到数据报 readable(也就是数据准备好了,可以被读取,readable 是 select 返回的值),当 select 返回 readable 时,说明数据报准备好了,此时就 recvfrom 接收数据,让数据报从内核空间拷贝到用户空间,拷贝完成后,recvfrom 返回成功,数据报也就成功的被用户程序所拥有了。

其实 select 并没有什么优势,反而略微有点劣势,因为它使用了两次系统调用,而不是一次。但是它的优势是它能够等待多个描述符准备好。

此模型也会阻塞,但是它可以等待多个描述符准备,因此还是有优势的。

4. 信号驱动的I/O

img

除了上面的方法,我们也可以使用信号,告诉内核当数据报准备好时,你就用信号通知我。

首先启动信号驱动I/O的socket,然后安装一个使用sigaction系统调用的signal handler,这个系统调用是立即返回的,并且返回后还继续执行,它是非阻塞的,当数据报准备好时,就会生成SIGIO信号,我们可以调用recvfrom从signal handler读取数据,并且告诉主循环数据已经准备好被获取了;或者我们可以通知主循环,让它自己读取数据。

此模型第一个阶段是非阻塞的,主循环可以做别的事情,但是从内核拷贝数据到用户的过程,是阻塞的。

5. 异步I/O

img

异步I/O是完全不阻塞的模型,它调用aio_read,会立刻返回,在等待I/O的过程中,进程是完全不阻塞的,我们猜测它可能在I/O完成时(这里的完成 包括从内核拷贝数据到用户)生成一个signal,这是它和信号I/O不同的地方(信号I/O不会拷贝数据到用户)

五种模型的比较:

img

简单来讲,如果把等待数据准备过程比作钓鱼时等待鱼上钩,把从内核拷贝数据到用户空间比作拉线收鱼,那么:

  1. 阻塞I/O:守着一个鱼竿一直等待鱼上钩,期间不干别的事情,就等着,鱼上钩了就拉线取走鱼。

  2. 非阻塞I/O: 弄个鱼竿搁在那儿,可以干别的事情去,每隔一段时间回来看一次有没有鱼上钩,直到有鱼上钩了,就拉线取走鱼。

  3. I/O 多路复用: 一次性弄好多鱼竿钓鱼(select就是可以同时等待多个描述符),这些鱼竿如果有任何一个有鱼上钩,就拉线取走鱼,没有的话就干等着鱼上钩,不干别的事情。

  4. 信号I/O: 给一个鱼竿弄个铃铛,然后自己干别的事情去,一旦铃铛响了,说明鱼上钩了,就过来取走鱼。

  5. 异步I/O:放个鱼竿钓鱼,然后自己干别的事情去,一旦鱼上钩了,鱼竿比较高级,自动把鱼拉上来放到桶里。

posted @ 2019-12-22 23:42  wztshine  阅读(544)  评论(0编辑  收藏  举报