「IO 模型」聊聊五种 IO 模型之概念篇
做一个比较注重七寸认知的技术人!
Hello,大家好!我是七寸君。
在系统架构中,高可用、高并发是系统架构的两个关键指标,也是架构复杂度所在。在高并发层面,目标就是在有限资源下,挖掘出无限的性能支撑。在这个过程中,网络 IO 的优化一直是关注的重点。
本文将先从 IO 模型基本概念说起,从概念认知层面达成一致,能够由浅入深的理解其原理。
概念说明
用户空间与内核空间
进程切换
为了控制进程的执行,内核必须有能力挂起正在 CPU 上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换。因此可以说,任何进程都是在操作系统内核的支持下运行的,是与内核紧密相关的。
从一个进程的运行转到另一个进程上运行,是很消耗资源的,这个过程中经过下面这些变化:
> 1. 保存处理机上下文,包括程序计数器和其他寄存器。
> 2. 更新 PCB 信息。
> 3. 把进程的 PCB 移入相应的队列,如就绪、在某事件阻塞等队列。
> 4. 选择另一个进程执行,并更新其 PCB。
> 5. 更新内存管理的数据结构。
> 6. 恢复处理机上下文。
进程阻塞
正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),使进程由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得CPU),才可能将其转为阻塞状态。当进程进入阻塞状态,是不占用CPU资源的。
文件描述符 fd
文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于 UNIX、Linux 这样的操作系统。
缓存 IO
缓存 IO 的缺点:
Linux IO 模型
所以说,当一个 read 操作发生时,它会经历两个阶段:
> 1. 第一阶段:等待数据准备 (Waiting for the data to be ready)。
> 2. 第二阶段:将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)。
对于 Socket 流而言:
> 1. 第一步:通常涉及等待网络上的数据分组到达,然后被复制到内核的某个缓冲区。
> 2. 第二步:把数据从内核缓冲区复制到应用进程缓冲区。
网络应用需要处理的无非就是两大类问题,网络 IO,数据计算。相对于后者,网络 IO 的延迟,给应用带来的性能瓶颈大于后者。网络 IO 的模型大致有如下几种:
> 1. 同步模型 IO(synchronous IO)
> 2. 阻塞 IO(bloking IO)
> 3. 非阻塞 IO(non-blocking IO)
> 4. 多路复用 IO(multiplexing IO)
> 5. 信号驱动式 IO(signal-driven IO)
> 6. 异步 IO(asynchronous IO)
由于 signal-driven IO 在实际中并不常用,所以我这只提及剩下的四种IO Model。
让我们来探索一下基本 Linux IO 模型的简单矩阵。如下图所示:
以上 IO 模型矩阵,每个 IO 模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点。
- EOF -
关注「七寸知架构」加星标,不错过技术那些事儿
❤️ 您的 点赞 和 在看 就是最大的支持❤️