4种常见IO模式详解

IO模式

本文讨论的背景是Linux环境下的网络IO。

对于一次IO访问,数据会先被拷贝到操作系统内核的缓冲区中,然后从操作系统内核的缓冲区拷贝到应用程序的地址空间。

所以,当发生一个IO操作,它会经历两个阶段:
1. 等待数据准备
2. 将数据从内核拷贝到进程中

对于两个阶段,linux系统产生了下面五种网络模式的IO存储方案。

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

注:信号驱动IO在实际中并不常用,所以我们讨论剩下的四种IO模式

 

阻塞IO:

在linux中,默认情况下所有的socket都是阻塞io

这个模式的特点在于,当用户进程调用了io操作的时候,操作系统就开始准备数据,操作系统内核一直等到数据准备好了,它就会将数据从操作系统内核中拷贝到用户内存,然后返回结果,用户进程才解除锁住的状态,重新运行起来。整个过程需要等待(不能立刻完成),而用户进程这边,就相当于是卡着一直在等他完成返回结果。

所以,阻塞IO的特点就是在IO执行的两个阶段都被锁住了

 

非阻塞 I/O(nonblocking IO)

linux下,可以通过设置socket使其变为非阻塞IO。

非阻塞IO的特点是,当用户进程发出IO操作时,在第一个阶段如果内核数据还没准备好,并不会锁住用户进程,而是立刻返回一个error。然后用户进程收到error,就知道没准备好,就会再去问内核有没有准备好,直到内核准备好,并且收到了用户进程的询问,就会立刻拷贝数据,然后进行第二阶段(第二阶段依然会卡住,非阻塞IO只是在第一阶段非阻塞)

就像打电话一样,对方占线,你就一直打,直到对方接通为止,但效率不高。所以,nonblocking IO的特点是用户进程需要不断的主动询问kernel数据好了没有。

 

I/O 多路复用( IO multiplexing)

IO多路复用就是我们的select,poll,epoll。当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。简单的说,就是和阻塞IO处理方式一样,但不同的是,select可以一下把很多很多文件描述符都传过来,然后操作系统内核同时监视他们,只要其中一个就绪,就及时处理那个,而不需要一个个等待处理。

他的性能可能比阻塞IO还要差,但他的优点在于能同时处理多个连接。所以,如果处理的连接数不是很高的话,使用IO多路复用不一定比使用多线程+阻塞IO的性能更好,可能延迟还更大。

 

异步 I/O(asynchronous IO)

Linux下的异步IO其实用得很少。

异步io的特点很简单:当处理一个io操作的时候,用户进程把数据传过来,操作系统会立刻返回“收到”,用户进程就不用管了,可以干别的事情了。等操作系统内核处理完2个阶段,就自动告诉用户进程我处理完了。

 

总结一下:

阻塞IO:用户一直等操作系统内核完成2个阶段io操作,再继续

非阻塞IO:第一阶段用户一直问操作系统有没有准备好,第二阶段等操作系统完成。

IO多路复用:用户进程可以同时发多个网络连接IO,操作系统实施监控,虽然用户进程2个阶段都卡住了,但可以处理多个连接。

异步IO:用户进程完全把东西交给操作系统完成,自己不管了。

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/likunkun__/article/details/82958228
今日推荐