【Linux基础】Linux的5种IO模型详解

引入

为了更好的理解5种IO模型的区别,在介绍IO模型之前,我先介绍几个概念

1.进程的切换

(1)定义

为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。即从用户态(较低的3G字节)切换到内核态(最高的1G字节),非常消耗系统资源。

(2)过程

  • 保存处理机上下文,包括程序计数器和其他寄存器。
  • 更新PCB信息。
  • 把进程的PCB移入相应的队列,如就绪、在某事件阻塞等队列。
  • 选择另一个进程执行,并更新其PCB。
  • 更新内存管理的数据结构。
  • 恢复处理机上下文。

2.进程的阻塞

(1)定义

正在执行的进程,由于期待的某些事件未发生,由运行状态变为阻塞状态。

(2)特点

  • 只有处于运行状态的进程(获得CPU)才能被阻塞
  • 阻塞是主动行为
  • 不占用CPU资源

3.文件描述符

(1) 定义

扫描二维码关注公众号,回复: 2545728 查看本文章

用于描述指向文件的引用的抽象化概念

(2) 特点

  • 一个非负整数
  • 本质是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表

4.缓存IO

  • IO的数据缓存在文件系统的页缓存中(先拷贝到内核的缓冲区)

  • 在应用程序和内核间多次数据拷贝,带来很大的CPU开销

5.并发与并行

  • 并发:同时进行的任务数

  • 并行:同时工作的物理资源数量(如CPU核数)

5种IO模型

  • IO的本质是socket的读取,数据先拷贝到内核的缓冲区中,然后拷贝到应用程序的地址空间(进程)

1.BIO(blocking IO):同步阻塞 I/O

(1)过程

这里写图片描述

分析:从上图可以看到在整个过程中,当用户进程进行系统调用时,内核就开始了I/O的第一个阶段,准备数据到缓冲区中,当数据都准备完成后,则将数据从内核缓冲区中拷贝到用户进程的内存中,这时用户进程才解除block的状态重新运行。

(2)实例

  • Blocking I/O是在I/O执行的两个阶段都被block了。

  • 例如:我要去饭堂吃饭,这时饭堂的人很多,我就得排队买饭,排队的时间被浪费了,

(3)特点

  • 能够及时返回数据,无延迟
  • 性能下降

2.NIO(nonblocking IO):同步非阻塞 I/O

(1)过程

这里写图片描述

分析:从上图可以看到在I/O执行的两个阶段中,用户进程只有在第二个阶段被阻塞了,而第一个阶段没有阻塞,但是在第一个阶段中,用户进程需要盲等,不停的去轮询内核,看数据是否准备好了。

(2)实例

  • nonblocking I/O是在I/O执行的第二个阶段(数据复制)被block了,而第一个阶段并未阻塞(数据准备)。

  • 例如:我要去饭堂吃饭,这时饭堂的人很多,一般来说我需要排队买饭,但我们饭堂的管理最近变的比较人性化,你点完饭后,会给你一个号码,但饭堂噪声很大,我不得不频繁的询问我的饭是否做好了,但是我可以利用之前排队的时间去买瓶饮料喝!

(3)特点

  • 拷贝数据的整个过程,进程仍然是阻塞的
  • 需要不断询问数据是否准备好了
  • 能够在等待任务完成的过程中处理其他事件
  • 由于需要轮询,所以延迟会增加

3.多路复用IO( IO multiplexing)

(1)过程

这里写图片描述

分析:

  • 从上图可以看到在I/O复用模型中,由于同步非阻塞方式需要不断主动轮询,轮询占据了很大一部分过程,轮询会消耗大量的CPU时间,而 “后台” 可能有多个任务在同时进行,

  • 如果循环查询多个任务的完成状态,只要有任何一个任务完成,就去处理它。轮询不是进程的用户态。这时 “IO 多路复用”就出现了。即UNIX/Linux 的 select、poll、epoll,

  • IO多路复用是阻塞在select,epoll这样的系统调用之上,而没有阻塞在真正的I/O系统调用如recvfrom之上。

  • 从整个IO过程来看,他们都是顺序执行的,因此可以归为同步模型(synchronous)。都是进程主动等待且向内核检查状态

(2)实例

  • 多路复用I/O执行的两个阶段用户进程都是阻塞的,但是两个阶段是独立的。

  • 例如:我要去饭堂吃饭,这时饭堂的人很多,点完饭后,我会拿到一个号码,以前我不得不频繁的询问我的饭做好了没,但是最近饭堂安装了一块电子显示屏,你的饭好了就会在屏上显示出来,这时候我就不用频繁的去问了,直接看电子显示屏就醒了,然后我就可以利用这个时间去超市买个牙膏了。

(3)特点

  • select/poll调用后会阻塞进程,但可以同时阻塞多个IO事件操作(文件描述符),有数据可读或可写(就绪事件),就通知用户进程。

  • select 需要每次注册事件(轮询),而epoll不需要每次注册事件(没有轮询,回调函数)

  • IO多路复用阻塞在select/epoll的系统调用之上的,而真正的IO系统调用如recvfrom是非阻塞的。

(4)适用场景

  • 服务器需要同时处理多个处于监听状态或连接状态的套接字

  • 服务器需要处理多种网络协议的套接字

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

(1)过程

这里写图片描述

分析:从上图可以看出,只有在I/O执行的第二阶段阻塞了用户进程,而在第一阶段是没有阻塞的。该模型在I/O执行的第一阶段,当数据准备完成之后,会主动的通知用户进程数据已经准备完成,即对用户进程做一个回调。该通知分为两种,一为水平触发,即如果用户进程不响应则会一直发送通知,二为边缘触发,即只通知一次。

(2)实例

  • 信号驱动I/O执行的第一阶段阻塞,而第二阶段不阻塞。

  • 例如:我要去饭堂吃饭,这时饭堂的人很多,点完饭后,我会拿到一个号码,虽然说饭堂安装了一块电子显示屏,但我在玩手机时还不得不抬头看一下显示屏上有我的号码没,最近饭堂买了一个大喇叭,哪个号码好了,卖饭的阿姨就会用喊,虽说饭堂有点吵,但这个声音还是可以听到的,这样我就可以专心的低头玩手机了。

5.异步 I/O(asynchronous IO)

(1)过程

这里写图片描述

分析:从上图可以看出,在该模型中,当用户进程发起系统调用后,立刻就可以开始去做其它的事情,然后直到I/O执行的两个阶段都完成之后,内核会给用户进程发送通知,告诉用户进程操作已经完成了。

(2)实例

  • 异步 I/O执行的两个阶段都不会阻塞。

  • 例如:我要去饭堂吃饭,估计这会饭堂的人很多,但最近我们饭堂可以叫外卖了,这样就省事多了,我直接打个电话,订份饭送到我们宿舍,而我现在就可以利用原来去饭堂路上和等饭的时间写博客了。

  • 这就是同步和异步的区别,原来我得亲自去饭堂买饭,而现在我可以在宿舍叫外卖。

(3)特点

  • 读写操作由内核完成,完成后内核将数据放到指定的缓冲区,通知应用程序来取。

总结

这里写图片描述

  • 阻塞IO和非阻塞IO的区别:数据准备的过程中,进程是否阻塞。

  • 同步IO和异步IO的区别:数据拷贝的过程中,进程是否阻塞。



本人才疏学浅,若有错,请指出,谢谢! 
如果你有更好的建议,可以留言我们一起讨论,共同进步! 
衷心的感谢您能耐心的读完本篇博文!

参考资料:聊聊Linux 五种IO模型

猜你喜欢

转载自blog.csdn.net/sinat_35297665/article/details/81171073