Linux_I/O模型

隐身守侯 提交于 2020-01-23 11:31:02

I/O模型(I/O Models)


  • 阻塞式I/O(blocking I/O)
  • 非阻塞式I/O(nonblocking I/O)
  • I/O多路复用(I/O multiplexing)
  • 信号驱动I/O(signal driven I/O)
  • 异步I/O(asynchronous I/O)

对于一个network I/O涉及两个系统对象,一个是调用I/O的进程(process),另一个是系统内核(kernel)。

下面用read操作来当做例子,当一个read操作发生时涉及的两个步骤:

  • 等待内核将数据准备好
  • 内核将准备好的数据拷贝到进程,也就是从kernel space拷贝到user space

对于一个socket的read操作,第一步通常是等待网络数据。当包到达时,会先拷贝到内核的内存中。然后第二步,把数据从内核的缓冲区拷贝到应用程序的缓冲区。


阻塞式I/O(blocking I/O)

在这里插入图片描述

姜太公钓鱼,愿者上钩。鱼竿丢下去,就等到鱼上来,啥事不干,啥事也干不了。

当应用程序调用recvfrom这个system call,kernel只有等到准备好数据,把数据拷贝到应用程序的缓冲区,才会返回。应用程序在调用recvfrom后,如果kernel没有准备好数据,会被“睡觉”。进程一直阻塞着,在呼叫recvfrom这个system call之后,直到kernel返回数据,或者错误。

blocking IO的特点就是在IO执行的两个阶段都被block了。


非阻塞式I/O(nonblocking I/O)

在这里插入图片描述

鱼竿下去,想看B站,看一会B站,看一下鱼钓到没。

非阻塞式I/O和阻塞式I/O很大的区别就在于,应用程序调用recvfrom,马上会有返回,如果kernel还没准备好数据,会返回错误EWOULDBLOCK。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。应用程序收到error的返回,会再呼叫recvfrom。如果kernel准备好数据,就会把数据拷贝到应用程序的缓存区,返回。

如果一个应用程序处于类似循环呼叫recvfrom这个操作,这个称为polling,轮询

这个模型比较浪费CPU时间。

注意,非阻塞式I/O算是同步I/O,虽然在呼叫recvfrom会立刻收到返回,但是在copy datagram那里是阻塞的,所以算是同步I/O


I/O复用(I/O Multiplexing Model)

在这里插入图片描述

一个鱼竿太少了,就买20根鱼竿,不断看哪根鱼竿钓到鱼了。

I/O复用,相比阻塞式I/O和非阻塞式I/O,会呼叫两个system call,一般由select,poll,epoll实现。这里用select先 当例子。

应用程序在呼叫select之后被阻塞,直到返回有data可以读。当select返回有data可以读,应用程序就呼叫recvfrom把data copy到应用程序的缓冲区。

相比较阻塞式I/O和非阻塞式I/O,这个模式没有优化什么,但是最大的优点是可以处理多条连接

在IO multiplexing Model中,实际中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。


信号I/O(Signal-Driven I/O Model)

在这里插入图片描述

鱼竿挂个铃,丢下去,等铃响了就收竿了。


异步I/O(Asynchronous I/O Model)

在这里插入图片描述

鱼竿丢下去,雇个小弟在那帮我看,钓到了,打电话告诉我鱼钓了,然后回去收鱼。

异步I/O根据POSIX标准定义。

应用程序呼叫aio_read(POSIX异步I/O方法用aio_或lio_开头)。系统会马上返回并且应用程序没有被阻塞,而是继续执行。等到kernel准备好数据,并且拷贝到应用程序的缓冲区后,会给应用程序数据一个signal(应用程序通常告诉kernel怎么通知),告诉应用程序read操作已经好了。

和信号驱动I/O不同的是,异步I/O的应用程序整个进程都不会被阻塞,kernel拷贝好数据后,通知应用程序。而信号驱动,只是在数据可读后通知应用程序,还要再呼叫recvfrom去让kernel拷贝数据。


比较

blocking I/O vs nonblocking I/O

blocking:阻塞式I/O,非阻塞式I/O,I/O复用,信号驱动I/O

nonblocking:异步I/O

blocking IO会一直block住对应的进程知道相应操作完成,而nonblocking IO会在kernel还在准备数据的时候就返回,继续执行。

asynchronous I/O vs synchronous I/O

synchronous:阻塞式I/O,非阻塞式I/O,I/O复用,信号驱动I/O

asynchronous :异步I/O

POSIX对这两个名词的定义是:

  • 一个同步I/O操作会导致进程阻塞直到该I/O操作完成
    A synchronous I/O operation causes the requesting process to be blocked until that
    I/O operation completes.
  • 一个异步I/O操作不会导致进程被阻塞
    An asynchronous I/O operation does not cause the requesting process to be blocked.

在这里插入图片描述


资料来源

<<UNIX Network Programming(Volume1,3rd)>> 6.2章

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!