2024-10-18 17:40:52 +08:00

146 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 第一章:输入输出模型
## 1.1 回顾冯·诺依曼体系结构
* `冯·诺依曼`体系结构的理论要点如下:
-**存储程序**`程序指令``数据`都存储在计算机的内存中,这使得程序可以在运行时修改。
-**二进制逻辑**:所有`数据``指令`都以`二进制`形式表示。
-**顺序执行**:指令按照它们在内存中的顺序执行,但可以有条件地改变执行顺序。
-**五大部件**:计算机由`运算器``控制器``存储器``输入设备``输出设备`组成。
-**指令结构**:指令由操作码和地址码组成,操作码指示要执行的操作,地址码指示操作数的位置。
-**中心化控制**计算机的控制单元CPU负责解释和执行指令控制数据流。
![img](./assets/1.png)
> [!NOTE]
>
> 上述的组件协同工作,构成了一个完整的计算机系统:
>
> - `运算器`和`控制器`通常被集成在一起组成中央处理器CPU负责数据处理和指令执行。
> - `存储器`(内存)保存数据和程序,是计算机运作的基础。
> - `输入设备`和`输出设备`负责与外界的交互,确保用户能够输入信息并接收计算机的处理结果。
>
> 直到今天,即使硬件的发展日新月异,但是现代计算机的硬件理论基础还是《冯·诺依曼体系结构》。
## 1.2 冯·诺依曼体系结构的瓶颈
* 计算机是有性能瓶颈的:如果 CPU 有每秒处理 1000 个服务请求的能力,各种总线的负载能力能达到 500 个, 但网卡只能接受 200个请求而硬盘只能负担 150 个的话,那这台服务器得处理能力只能是 150 个请求/秒,有 85% 的处理器计算能力浪费了,在计算机系统当中,`硬盘`的读写速率已经成为影响系统性能进一步提高的瓶颈。
![](./assets/2.jpg)
* 计算机的各个设备部件的延迟从高到低的排列依次是机械硬盘HDD、固态硬盘SSD、内存、CPU 。
![](./assets/3.png)
* 从上图中我们可以知道CPU 是最快的,一个时钟周期是 0.3 ns ,内存访问需要 120 ns ,固态硬盘访问需要 50-150 us传统的硬盘访问需要 1-10 ms而网络访问是最慢需要 40 ms 以上。
> [!NOTE]
>
> 时间的单位换算如下:
>
> * ① 1 秒 = 1000 毫秒,即 1 s = 1000 ms。
> * ② 1 毫秒 = 1000 微妙,即 1 ms = 1000 us 。
> * ③ 1 微妙 = 1000 纳秒,即 1 us = 1000 ns。
* 如果按照上图,将计算机世界的时间和人类世界的时间进行对比,即:
```txt
如果 CPU 的时钟周期按照 1 秒计算,
那么,内存访问就需要 6 分钟;
那么,固态硬盘就需要 2-6 天;
那么,传统硬盘就需要 1-12 个月;
那么,网络访问就需要 4 年以上。
```
> [!NOTE]
>
> * ① 这就中国古典修仙小说中的“天上一天,地上一年”是多么的相似!!!
> * ② 对于 CPU 来说,这个世界真的是太慢了!!!
* 其实,中国古代中的文人,通常以`蜉蝣`来表示时间的短暂(和其他生物的寿命比),也是类似的道理,即:
```txt
鹤寿千岁,以极其游,蜉蝣朝生而暮死,尽其乐,盖其旦暮为期,远不过三日尔。
--- 出自 西汉淮南王刘安《淮南子》
```
```txt
寄蜉蝣于天地,渺沧海之一粟。 哀吾生之须臾,羡长江之无穷。
挟飞仙以遨游,抱明月而长终。 知不可乎骤得,托遗响于悲风。
--- 出自 苏轼《赤壁赋》
```
> [!NOTE]
>
> * ① 从`蜉蝣`的角度来说,从早到晚就是一生;但是,从`人类`角度来说,从早到晚却仅仅只是一天。
> * ② 这和“天上一天,地上一年”是多么的相似,即:如果`蜉蝣`是`人类`的话,那`我们`就是`仙人`了。
* 存储器的层次结构CPU 中也有存储器,即:寄存器、高速缓存 L1、L2 和 L3如下所示
![img](./assets/4.png)
> [!NOTE]
>
> 上图以层次化的方式,展示了价格信息,揭示了一个真理,即:鱼和熊掌不可兼得。
>
> - ① 存储器越往上速度越快,但是价格越来越贵, 越往下速度越慢,但是价格越来越便宜。
> - ② 正是由于计算机各个部件的速度不同,容量不同,价格不同,导致了计算机系统/编程中的各种问题以及相应的解决方案。
* 正是由于 CPU、内存以及 IO 设备之间的速度差异,从而导致了计算机的性能瓶颈,即所谓的`“冯·诺依曼体系结构的瓶颈”`
![](./assets/5.svg)
* 因为 CPU 的处理速度远远快于内存和 IO 设备导致在等待数据处理和传输的时候CPU 大部分处于空闲状态。就是这种显著的速度差异就导致了计算机的性能瓶颈,限制了整个计算机系统的效率。
> [!NOTE]
>
> * 对于硬件的这种显著的速度差异,我们程序员是无法解决的。
> * 但是,为了平衡三者之间的速度鸿沟,我们可以通过引入`缓冲区`技术,来降低系统的 IO 次数,降低系统的开销。
* 其实,在硬件上也是有`缓冲区`CPU 内部集成了缓存,将经常使用到的数据从内存中加载到缓存中。
> [!NOTE]
>
> 对于缓存和内存中数据的同步解决方案会有各种各样的算法LRU 等。
![](./assets/6.svg)
## 1.3 缓冲区
### 1.3.1 概述
* 我们所编写的程序,都是运行在内存中的,如果我们不使用缓冲区,那么其在内存中就是这样的,如下所示:
![](./assets/7.svg)
* 而缓冲区的本质就是在`内存`中开辟一块用来`临时存储数据``区域`,它在速度较慢的内存和 IO 设备起到了桥梁的作用,那么其在内存中就是这样的,如下所示:
![](./assets/8.svg)
> [!NOTE]
>
> 其实C 语言中的 `printf` 函数和 `scanf` 函数,其内部就使用了缓冲区。
>
> * ① 当我们使用 `printf` 函数输出数据的时候,数据并不会立即就写出到输出设备(如:屏幕等)。而是先将其放置到 `stdout 缓冲区`中,然后在满足条件的时候,再从缓冲区中刷新到输出设备。
> * ② 当我们使用 `scanf` 函数输入数据的时候,数据并不会立即就从输入设备中读取(如:键盘等)。而是先将其放置到 `stdin 缓冲区`中,然后在满足条件的时候,再从缓冲区中加载数据。
### 1.3.2 缓冲区到底如何实现系统效率的提升?
* 如果没有缓冲区,假设有 5 个数据,输入设备每次传递 1 个数据CPU 必须立即接收并处理,因此有 5 次 IO 操作,每次都是逐个处理,如下所示:
![](./assets/9.svg)
* 如果没有缓冲区,假设有 5 个数据,输入设备每次传递 1 个数据但它们先存储到缓冲区中。CPU 在缓冲区满时一次性处理多个数据,减少了频繁的等待,如下所示:
![](./assets/10.svg)
> [!IMPORTANT]
>
> 假设每次 IO 操作的时间是 1 秒CPU 处理数据的时间也是 1 秒,那么:
>
> * ① 没有缓冲区的情况下总耗时是5 次 I/O 操作 + 5 次处理 = 10 秒,即:没有缓冲区的情况下,每次 I/O 操作和处理器的处理是交替进行的,因此总共需要 10 秒5 次 I/O + 5 次处理)
> * ② 使用缓冲区的情况下总耗时是5 次 I/O 操作 + 1 次批量处理 = 6 秒使用缓冲区的情况下I/O 操作和处理器处理是分开的I/O 操作先全部完成,处理器一次性批量处理所有数据。因此,总耗时减少为 6 秒5 秒传输 + 1 秒处理)。
>
> 使用缓冲区能够显著减少总的执行时间,因为它允许处理器批量处理数据,而不是在每次数据传递后都进行等待处理。