在 1945 年冯诺依曼和其他计算机科学家们提出了计算机具体实现的报告,其遵循了图灵机的设计,而且还提出用电子元件构造计算机,并约定了用二进制进行计算和存储。
最重要的是定义计算机基本结构为 5 个部分,分别是运算器、控制器、存储器、输入设备、输出设备,这 5 个部分也被称为冯诺依曼模型。
下图为冯 • 诺依曼体系结构流程图:
运算器、控制器是在中央处理器里的,存储器就是我们常见的内存,输入输出设备则是计算机外接的设备,比如键盘就是输入设备,显示器就是输出设备。
我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系,截至目前,我们所认识的计算机,都是有一个个的硬件组件组成。
存储单元和输入输出设备要与中央处理器打交道的话,离不开总线。所以,它们之间的关系如下图:
接下来,分别介绍内存、中央处理器、总线、输入输出设备。
输入设备向计算机输入数据,计算机经过计算后,把数据输出给输出设备。
常见的输入和输出设备有:
注意: 同种设备在不同场景下可能属于输入设备,也可能属于输入设备。
中央处理器也就是我们常说的 CPU,它是由运算器和控制器组成。
CPU 内部还有一些组件,常见的有 寄存器、控制单元 和 逻辑运算单元 等。其中,控制单元负责控制 CPU 工作,逻辑运算单元负责计算,而寄存器可以分为多种类,每种寄存器的功能又不尽相同。
CPU 中的寄存器主要作用是存储计算时的数据,你可能好奇为什么有了内存还需要寄存器?原因很简单,因为内存离 CPU 太远了,而寄存器就在 CPU 里,还紧挨着控制单元和逻辑运算单元,自然计算时速度会很快。
常见的寄存器种类:
内存,也就是所谓的存储器。
我们的程序和数据都是存储在内存,存储的区域是线性的。
在计算机数据存储中,存储数据的基本单位是字节(byte),1 字节等于 8 位(8 bit)。每一个字节都对应一个内存地址。
内存的地址是从 0 开始编号的,然后自增排列,最后一个地址为内存总字节数 - 1,这种结构好似我们程序里的数组,所以内存的读写任何一个数据的速度都是一样的。
思考一个问题: 当我们的体系结构中,有了输入、输出设备和 CPU 以后,就能正常工作了,那么为什么还需要内存呢?
(1)从技术角度来说
CPU 的运算速度 > > > 寄存器的速度 > > > L1~L3Cache > > > 内存 > > > 外设(磁盘) > > > 光盘磁带
也就是说,输入设备和输出设备相对于 CPU 来说是非常慢的。
如果没有内存的话,那么当前这个体系整体呈现出来的就是:输入设备和输出设备很慢,而 CPU 很快。
相信大家知道 木桶原理 吧,那么最终整个体系结构所呈现出来的速度将会是很慢的。
所以,从数据角度出发,外设几乎不和 CPU 打交道,它是直接和内存打交道,CPU 也同样如此。
进言之,内存在我们看来,就是体系结构的一个大的缓存,用来适配外设和 CPU 速度不均的问题!
(2)从成本角度来说
既然上面说了内存是用来适配外设和 CPU 速度不均的问题,那么为什么不直接在 CPU 里面开发一个类似于内存的东西呢?
这个想法可以,但是如果真要去实现的话,那么一台计算机的成本起码得 10W+,而计算机它是蔓延全世界的,也就是说人人都能用得起的!
寄存器的价格 > > > 内存 > > > 外设(磁盘)
所以内存就是方便我们使用较低的成本,获得较高的性能。
总线是用于 CPU 和内存以及其他设备之间的通信,总线可分为 3 种:
当 CPU 要读写内存数据的时候,一般需要通过下面这三个总线:
我相信大家应该还有个疑惑:就是,先将输入设备的数据交给内存,再由内存将数据交给 CPU,这个过程真的比 CPU 直接从输入设备获取数据更快吗?
说明这个问题之前,我们首先需要知道:内存具有数据存储的能力。虽然内存的大小只有 4G/8G,但是既然内存有大小,那么它就有预装数据的能力,而这就是提高该体系结构效率的秘诀。
这里不得不说到的就是 局部性原理:根据统计学原理,当一个数据正在被访问时,那么下一次有很大可能会访问其周围的数据。所以当 CPU 需要获取某一行数据时,内存可以将该行数据之后的数据一同加载进来,而 CPU 处理数据和内存加载数据是可以同时进行的,这样下次 CPU 就可以直接从内存当中获取数据。
输出数据的时候也一样,CPU 处理完数据后直接将数据放到内存当中,当输出设备需要时再在内存当中获取即可,这也就有了我们平常所说的缓冲区的概念。
例如,缓冲区满了才将数据打印到屏幕上,使用 fflush 函数将缓冲区当中的数据直接输出之类的,都是将内存当中的数据直接拿到输出设备当中进行显示输出。
冯 • 诺依曼体系结构核心原理为:用户输入的数据先放到内存当中,CPU 读取数据的时候就直接从内存当中读取,CPU 处理完数据后又写回内存当中,然后内存再将数据输出到输出设备当中,最后由输出设备进行输出显示。
我们可以知道,站在硬件角度或是数据层面上,CPU 和外设不能直接交互,而是通过内存,也就是说,所有设备都只能和内存打交道。
由此可以说明一个问题:为什么程序运行之前必须先加载到内存?
因为可执行程序(文件)是在硬盘(外设)上的,而 CPU 只能从内存当中获取数据,所以必须先将硬盘上的数据加载到内存,也就是必须先将程序加载到内存。
对冯诺依曼的理解,不能停留在概念上,要深入到对软件数据流理解上。
从你登录上 QQ 和某位朋友聊天开始,数据的流动过程是怎样的呢?从你打开窗口,开始给他发消息,到他的到消息之后的数据流动过程。
要使用 QQ,首先需要联网,而你和你的朋友的电脑都是冯诺依曼体系结构,在你向朋友发送消息这个过程中,你的电脑当中的键盘充当输入设备,显示器和网卡充当输出设备,你朋友的电脑当中的网卡充当输入设备,显示器充当输出设备。
刚开始你在键盘当中输入消息,键盘将消息加载到内存,此时你的显示器就可以从内存获取消息进而显示在你自己的显示器上,此时你就能在你自己的电脑上看到你所发的消息了。
在键盘将消息加载到内存后,CPU 从内存获取到消息后对消息进行各种封装,然后再将其写回内存,此时你的网卡就可以从内存获取已经封装好的消息,然后在网络当中经过一系列处理(这里忽略网络处理细节)。
之后你朋友的网卡从网络当中获取到你所发的消息后,将该消息加载到内存当中,你朋友的 CPU 再从内存当中获取消息并对消息进行解包操作,然后将解包好的消息写回内存,最后你朋友的显示器从内存当中获取消息并显示在他的电脑上。
那么如果是在 QQ 上发送文件呢?
首先你的文件最开始是在你本地的磁盘上的,先从磁盘上把文件读到内存中,文件里面的东西其实还是数据,把数据再经过 CPU 封装成报文,然后刷新到我们的内存中,定期再经过网卡,把数据刷新到网卡上,然后再发出去。
传文件的本质就是:两端的磁盘进行通信。