Linux IO模型

网络数据接收流程

计算机接收网络数据的流程如下

  1. 数据通过网线到达计算机
  2. 网卡接收到达的网络数据,将数据写入内核缓冲区
  3. 网卡向CPU发送一个中断信号,告知接收到数据
  4. CPU收到中断信号后,先将数据由内核拷贝到用户空间
  5. CPU唤醒对应进程,通知它处理数据

通过上图,我们可以知道,对于一次IO访问(以read为例),它会经历两个阶段

  1. 等待数据的到来
  2. 将数据从内核拷贝到用户空间

根据不同阶段不同操作,Linux设计了4种不同的IO的模型。

4种IO模型

阻塞IO(Blocking IO)

对于阻塞IO,当进程调用recefrom这个系统调用,就进入了第一阶段,进程将被阻塞。当数据接收完成之后,内核开始拷贝数据,此时进入第二阶段。当数据拷贝完毕之后,将通知来处理数据。

阻塞IO的特点就是在两个阶段进程都被阻塞了

非阻塞IO(Nonblocking IO)

对于非阻塞IO,当进程调用recefrom系统调用时,此时若数据还没准备好,内核会返回一个ERROR,告知进程数据还没ready。进程收到结果之后,便知数据还未到达,于是它继续发送recefrom系统调用,直到数据ready,进入第二阶段

非阻塞IO的非阻塞是指在第一阶段进程没有被阻塞,可以收到系统调用结果

非阻塞IO在第一阶段采用的轮询的方式,不断询问内核数据是否ready

IO多路复用(IO multiplexing)

IO多路复用也就是常说的select,poll,epoll方式,是指进程可以同时处理多个网络IO请求。

当进程调用select时,进程将会被阻塞,直到select管理的socket中,有一个以上的socket接收到数据,此时进程将被唤醒,同时它遍历所有socket对象,以便确定是哪个socket接收到数据。关于select,poll,epoll的区别将在下一篇博客中进行分析。

IO多路复用在两个阶段都是被阻塞的,与阻塞IO相比,唯一的区别是它可以处理多个IO连接

异步IO(Asynchronous IO)

对于异步IO,进程发起recefrom的系统调用后,会立即收到返回结果,此时进程可以继续处理其他事情。当内核把数据接收完毕,同时拷贝到用户空间后,便发出一个signal给进程,通知进程来处理数据。

异步IO在两个阶段都没有被阻塞

总结

  1. 对于一次IO请求来说,都需要经历两个阶段,一是等待数据到来,二是等到内核把数据拷贝到用户空间
  2. 阻塞IO,非阻塞IO,IO多路复用都可以归类于同步IO,因为他们在第一个阶段或者第二阶段都会被阻塞,而异步IO在两个阶段都不会被阻塞
  3. 以吃饭为例子,可以对上述模型进行类比

     阻塞IO:我到饭店吃饭,点完餐之后就在餐桌上干等,之后饭做好我去拿
     非阻塞IO:点完餐之后,我每隔一段时间就去厨房问厨师饭是否做好,知道厨师告诉饭做好了
     异步IO:类似于点外卖,我告诉店家我要吃什么,店家做好之后直接把饭送到家里,在这段时间我可以干其他事情
    

参考文献


Reprint please specify: wbl Linux IO模型

Previous
初探Select,Poll,Epoll 初探Select,Poll,Epoll
在一个高性能的网络服务中,一个进程往往需要同时处理多个socket。在上一篇博客Linux IO模型中提到的IO多路复用模型就是为了解决这个问题的。 Select,Poll,EPoll是IO多路复用的三种机制,下面来具体看下三者之间的联系和
Next
数据链路层协议设计与实现(2) 数据链路层协议设计与实现(2)
捎带确认在上一篇数据链路层协议设计与实现(1)中,我们看到的几个协议,对于信道的利用率都不高,原因在于数据基本都是单向传输。对于停等协议和自动重传协议来说,其实数据已经是双向传输的,但是反向传输的都是ACK,这样利用率也不高。 针对上述的情