网络数据接收流程
计算机接收网络数据的流程如下
- 数据通过网线到达计算机
- 网卡接收到达的网络数据,将数据写入内核缓冲区
- 网卡向CPU发送一个中断信号,告知接收到数据
- CPU收到中断信号后,先将数据由内核拷贝到用户空间
- CPU唤醒对应进程,通知它处理数据
通过上图,我们可以知道,对于一次IO访问(以read为例),它会经历两个阶段
- 等待数据的到来
- 将数据从内核拷贝到用户空间
根据不同阶段不同操作,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在两个阶段都没有被阻塞
总结
- 对于一次IO请求来说,都需要经历两个阶段,一是等待数据到来,二是等到内核把数据拷贝到用户空间
- 阻塞IO,非阻塞IO,IO多路复用都可以归类于同步IO,因为他们在第一个阶段或者第二阶段都会被阻塞,而异步IO在两个阶段都不会被阻塞
以吃饭为例子,可以对上述模型进行类比
阻塞IO:我到饭店吃饭,点完餐之后就在餐桌上干等,之后饭做好我去拿 非阻塞IO:点完餐之后,我每隔一段时间就去厨房问厨师饭是否做好,知道厨师告诉饭做好了 异步IO:类似于点外卖,我告诉店家我要吃什么,店家做好之后直接把饭送到家里,在这段时间我可以干其他事情