01.计算机组成原理和结构
目录介绍
- 01.计算机底层知识
- 1.1 计算机基础组成
- 1.2 理论和实践相结合
- 02.计算机基本硬件
- 2.1 基本硬件组成
- 2.2 输入和输出设备
- 03.冯·诺依曼体系结构
- 3.1 存储程序计算机
- 3.2 冯·诺依曼描述计算机
- 3.3 抽象计算机框架
- 3.4 冯·诺依曼体系延伸
- 3.5 综合案例理解概念
- 3.6 数据交互层面设计
- 3.7 数据流动层面设计
- 3.8 控制层面设计思想
- 3.9 来看一道练习题
- 04.计算机组成原理
- 4.1 计算机知识地图
- 4.2 计算机基本组成
- 4.3 控制器
- 4.4 存储器
- 4.5 输入设备
- 4.6 输出设备
- 4.7 运算器
- 05.如何学习组成原理
- 5.1 知识体系太大了
- 5.2 如何学习该专栏
01.计算机底层知识
1.1 计算机基础组成
- 计算机是由 CPU、内存、显示器这些设备组成的硬件
- 目前,大部分程序员都是从事各种软件开发工作。显然,在硬件和软件之间需要一座桥梁,而“计算机组成原理”就扮演了这样一个角色,它既隔离了软件和硬件,也提供了让软件无需关心硬件,就能直接操作硬件的接口。
- 只需要对硬件有原理性的理解,就可以信赖硬件的可靠性,用高级语言来写程序。无论是写操作系统和编译器这样的硬核代码,还是写 Web 应用和手机 App 这样的应用层代码,都可以做到心里有底。
- 无论你想要学习计算机的哪一门核心课程,之前都应该先学习一下“计算机组成原理”,这样无论是对计算机的硬件原理,还是软件架构,对计算机方方面面的知识都会有一个全局的了解。
image
1.2 理论和实践相结合
- 说了这么多计算机组成原理的重要性,但到底该怎么学呢?
- “买书如山倒,读书如抽丝”。从业这么多年,周围想要好好学一学组成原理的工程师不少,但是真的坚持下来学完、学好的却不多。
- 对这些问题,从学习和工作的经验看,找到了三个主要原因。
- 第一,广。组成原理中的概念非常多,每个概念的信息量也非常大。比如想要理解 CPU 中的算术逻辑单元(也就是 ALU)是怎么实现加法的,需要牵涉到如何把整数表示成二进制,还需要了解这些表示背后的电路、逻辑门、CPU 时钟、触发器等知识。
- 第二,深。组成原理中的很多概念,阐述开来就是计算机学科的另外一门核心课程。比如,计算机的指令是怎么从你写的 C、Java 这样的高级语言,变成计算机可以执行的机器码的?如果我们展开并深入讲解这个问题,就会变成《编译原理》这样一门核心课程。
- 第三,学不能致用。学东西是要拿来用的,但因为这门课本身的属性,很多人在学习时,常常沉溺于概念和理论中,无法和自己日常的开发工作联系起来,以此来解决工作中遇到的问题,所以,学习往往没有成就感,就很难有动力坚持下去。
02.计算机基本硬件
2.1 基本硬件组成
- 早年,要自己组装一台计算机,要先有三大件,CPU、内存和主板。
- CPU,它是计算机最重要的核心配件,全名你肯定知道,叫中央处理器(Central Processing Unit)。为什么说 CPU 是“最重要”的呢?因为计算机的所有“计算”都是由 CPU 来进行的。自然,CPU 也是整台计算机中造价最昂贵的部分之一。
- 内存(Memory),你撰写的程序、打开的浏览器、运行的游戏,都要加载到内存里才能运行。程序读取的数据、计算得到的结果,也都要放在内存里。内存越大,能加载的东西自然也就越多。
- 主板,存放在内存里的程序和数据,需要被 CPU 读取,CPU 计算完之后,还要把数据写回到内存。然而 CPU 不能直接插到内存上,反之亦然。于是,就带来了最后一个大件——主板(Motherboard)。
2.2 输入和输出设备
- 有了三大件,只要配上电源供电,计算机差不多就可以跑起来了。但是现在还缺少各类输入(Input)/ 输出(Output)设备,也就是我们常说的 I/O 设备。
- 如果你用的是自己的个人电脑,那显示器肯定必不可少,只有有了显示器我们才能看到计算机输出的各种图像、文字,这也就是所谓的输出设备。
- 同样的,鼠标和键盘也都是必不可少的配件。这样我才能输入文本,写下这篇文章。它们也就是所谓的输入设备。
03.冯·诺依曼体系结构
3.1 存储程序计算机
- 因为,无论是个人电脑、服务器、智能手机,还是 Raspberry Pi 这样的微型卡片机,都遵循着同一个“计算机”的抽象概念。
- 这是怎么样一个“计算机”呢?这其实就是,计算机祖师爷之一冯·诺依曼(John von Neumann)提出的冯·诺依曼体系结构(Von Neumann architecture),也叫存储程序计算机。
- 什么是存储程序计算机呢?
- 这里面其实暗含了两个概念,一个是“可编程”计算机,一个是“存储”计算机。
- 说到“可编程”,估计你会有点懵,你可以先想想,什么是“不可编程”。
- 计算机是由各种门电路组合而成的,然后通过组装出一个固定的电路板,来完成一个特定的计算程序。一旦需要修改功能,就要重新组装电路。这样的话,计算机就是“不可编程”的,因为程序在计算机硬件层面是“写死”的。
- 最常见的就是老式计算器,电路板设好了加减乘除,做不了任何计算逻辑固定之外的事情。
- 再来看“存储”计算机。这其实是说,程序本身是存储在计算机的内存里,可以通过加载不同的程序来解决不同的问题。
- 有“存储程序计算机”,自然也有不能存储程序的计算机。
- 典型的就是早年的“Plugboard”这样的插线板式的计算机。整个计算机就是一个巨大的插线板,通过在板子上不同的插头或者接口的位置插入线路,来实现不同的功能。这样的计算机自然是“可编程”的,但是编写好的程序不能存储下来供下一次加载使用,不得不每次要用到和当前不同的“程序”的时候,重新插板子,重新“编程”。
3.2 冯·诺依曼描述计算机
- 冯祖师爷,描述了他心目中的一台计算机应该长什么样。
- 首先是一个包含算术逻辑单元(Arithmetic Logic Unit,ALU)和处理器寄存器(Processor Register)的处理器单元(Processing Unit),用来完成各种算术和逻辑运算。因为它能够完成各种数据的处理或者计算工作,因此也有人把这个叫作数据通路(Datapath)或者运算器。
- 然后是一个包含指令寄存器(Instruction Register)和程序计数器(Program Counter)的控制器单元(Control Unit/CU),用来控制程序的流程,通常就是不同条件下的分支和跳转。在现在的计算机里,上面的算术逻辑单元和这里的控制器单元,共同组成了我们说的 CPU。
- 接着是用来存储数据(Data)和指令(Instruction)的内存。以及更大容量的外部存储,在过去,可能是磁带、磁鼓这样的设备,现在通常就是硬盘。
- 最后就是各种输入和输出设备,以及对应的输入和输出机制。我们现在无论是使用什么样的计算机,其实都是和输入输出设备在打交道。个人电脑的鼠标键盘是输入设备,显示器是输出设备。我们用的智能手机,触摸屏既是输入设备,又是输出设备。而跑在各种云上的服务器,则是通过网络来进行输入和输出。这个时候,网卡既是输入设备又是输出设备。
3.3 抽象计算机框架
- 任何一台计算机的任何一个部件都可以归到运算器、控制器、存储器、输入设备和输出设备中,而所有的现代计算机也都是基于这个基础架构来设计开发的。
- 而所有的计算机程序,也都可以抽象为从输入设备读取输入信息,通过运算器和控制器来执行存储在存储器里的程序,最终把结果输出到输出设备中。
- 我们所有撰写的无论高级还是低级语言的程序,也都是基于这样一个抽象框架来进行运作的。
image
- 冯·诺依曼结构也称作普林斯顿结构,是一种将程序和数据存放在同一存储器不同地址的设计概念,其核心特点如下:
- 计算机由运算器、控制器、存储器、输入和输出设备五个部分组成
- 数据和程序均以二进制代码形式不加区分地存放在存储器中,具体位置由存储器地址决定
- 顺序执行程序,即计算机工作时,先把要执行的程序和处理的数据存入存储器 (内存),然后自动并按顺序从存储器中取出指令逐一执行
image
3.4 冯·诺依曼体系延伸
- 冯·诺依曼体系结构确立了我们现在每天使用的计算机硬件的基础架构。因此,学习计算机组成原理,其实就是学习和拆解冯·诺依曼体系结构。
- 具体来说,学习组成原理,其实就是学习控制器、运算器的工作原理,也就是 CPU 是怎么工作的,以及为何这样设计;学习内存的工作原理,从最基本的电路,到上层抽象给到 CPU 乃至应用程序的接口是怎样的;学习 CPU 是怎么和输入设备、输出设备打交道的。
- 学习组成原理,就是在理解从控制器、运算器、存储器、输入设备以及输出设备,从电路这样的硬件,到最终开放给软件的接口,是怎么运作的,为什么要设计成这样,以及在软件开发层面怎么尽可能用好它。
3.5 综合案例理解概念
- 假设在一个假期中,小杨突然想起了一个许久没有联系的朋友,随机在电脑中打开了QQ,在对话框中输入了要发送的消息,随即向朋友发送了过去。下图所示感性的描述了这个过程:
image
- 通过该综合案例理解冯诺依曼体系结构
- 小杨打开QQ软件,这个时候程序运行前,需要把它加载到内存中。这是由体系结构决定的,cpu只能从内存中读取数据,不会直接和外设拿“数据”。
- 写的代码要编译成二进制指令,是要交由cpu进行处理,因为cpu要根据接收到的指令来完成工作,当接收到二进制的指令后,分析好要处理的数据,根据和自己的指令集“比对”确定要怎样“处理”!
- 小杨通过键盘输入消息,这个过程称之为IO过程(input/output)。会将消息通过二进制在内存中传输,这个就涉及到内存和外设交互的过程
- 消息通过网络向朋友发去,朋友那边收到消息,二进制数据需要序列化,会首先加载数据到内存内存中。这个解决数据的过程是在CPU中进行的,CPU不和外设“打交道”,只和内存打交道。
- 最后,将消息打印到显示器中。这个是输出过程,输出通过IO流程,最终通过界面形式展现出来
3.6 数据交互层面设计
- 冯诺依曼体系结构,在数据交互层面是如何设计的
- CPU不会和外设直接打交道,只会和内存交互
- 所有的外设如果有数据需要载入只能载入到内存,内存写出的数据也一定是写到外设中去
- 这样做的目的是为了提高整机的效率
- **原因:**我们都知道一个木桶原理,就是一个木桶里面能装多少水不是取决于最长的木板而是取决于最短的木板。
- 计算机也是类似的,CPU就像是那个最长的木板,如果在进行数据交互的时候每次CPU都和外设交互,那么CPU那么快的速度就没用了。
- 所以在数据交互的时候要让外设中的数据在CPU需要之前载入内存,CPU需要的时候就直接去内存中拿就可以了。内存的速度是比外设快很多的,所以可以提高征整机的效率。
- 为什么程序运行之前要先载入内存?
- 因为CPU要执行我们的代码,访问数据,只能访问内存。这时体系结构所规定的。
3.7 数据流动层面设计
- 举例现在你在和你的网友进行QQ聊天,你发了一条消息到网友接受到消息中间经历了那些硬件?
image
- 完整的数据流动是什么样的
- 首先你将消息通过键盘输入,载入到内存中属于QQ的那块空间,然后通过CPU对消息进行处理(加密之类的)然后再写回内存中,内存将数据写到网卡中。
- 通过网络发送到网友电脑的网卡,然后将接受到的数据写入内存,CPU处理后再写回内存,从内存再写到显示器上。
3.8 控制层面设计思想
- 当我们通过键盘将数据输入,内存是如何知道外设中有数据需要加载到内存中呢?
- 当内存中的数据要往磁盘的写的话是什么时候写的(肯定不是随时写的,太慢了)也就是缓冲区是什么时候清空的呢。
1_3_8_image
- 这里的黑色箭头是控制信号,也就是说CPU的控制器负责了我们上面的操作。
- 控制器又是在执行谁的指令来控制这些外设和内存呢?实际是操作系统(Operator System),操作系统是在幕后一直帮助CPU进行决策的。
3.9 来看一道练习题
- 例题:冯诺依曼机的基本工作方式是:
- A.控制流驱动方式;B.多指令多数据流方式;C.微程序控制方式;D.数据流驱动方式
- 答案:A;冯·诺依曼机工作方式,可称为控制流(指令流)驱动方式。
- 即按照指令的执行序列,依次读取指令,然后根据指令所含的控制信息,调用数据进行处理。
- B属于多处理机,冯诺依曼机是单指令流和单数据流系统;数据流驱动方式指:只有当一条或一组指令所需的操作数全部准备好时,才能激发相应指令的一次执行,执行结果又流向等待这一数据的下一条或一组指令,以驱动该条或该组指令的执行。
- 因此,程序中各条指令的执行顺序仅仅是由指令间的数据依赖关系决定的。
- 存储程序的概念是指将指令以代码形式事先输入计算机的主存储器,然后按其在存储器中的首地址执行程序的第一条指令,以后就按程序的规定顺序执行其他指令,直至程序执行结束。
1_3_9_image
04.计算机组成原理
4.1 计算机知识地图
- 从这张图可以看出来,整个计算机组成原理,就是围绕着计算机是如何组织运作展开的。
image
4.2 计算机基本组成
- 计算机是由哪些硬件组成的。这些硬件,又是怎么对应到经典的冯·诺依曼体系结构中的,也就是运算器、控制器、存储器、输入设备和输出设备这五大基本组件。
- 除此之外,你还需要了解计算机的两个核心指标,性能和功耗。性能和功耗也是我们在应用和设计五大基本组件中需要重点考虑的因素。
- 在计算机指令部分,需要搞明白,我们每天撰写的一行行 C、Java、PHP 程序,是怎么在计算机里面跑起来的。
- 这里面,你既需要了解我们的程序是怎么通过编译器和汇编器,变成一条条机器指令这样的编译过程(如果把编译过程展开的话,可以变成一门完整的编译原理课程),还需要知道我们的操作系统是怎么链接、装载、执行这些程序的(这部分知识如果再深入学习,又可以变成一门操作系统课程)。
- 而这一条条指令执行的控制过程,就是由计算机五大组件之一的控制器来控制的。
- 在计算机的计算部分,要从二进制和编码开始,理解我们的数据在计算机里的表示,以及我们是怎么从数字电路层面,实现加法、乘法这些基本的运算功能的。
- 实现这些运算功能的 ALU(Arithmetic Logic Unit/ALU),也就是算术逻辑单元,其实就是我们计算机五大组件之一的运算器。
4.3 控制器
- 控制器是计算机的指挥中心,由其指挥各部件自动协调地进行工作。控制器由程序计数器PC、指令寄存器IR和控制单元CU组成。
- PC用于存放当前欲执行指令的地址,可自动+1以形成下一条指令的地址,与主存的MAR之间有一条直接通路。
- IR用来存放当前的指令,其内容来自主存的MDR。指令中的操作码OP(IR)送至CU,用以分析指令并发出各种微操作命令序列;地址码Ad(IR)送往MAR,用以取操作数。(操作码表示机器所执行的各种操作,地址码表示参加运算的数在存储器内的位置)
1_4_3_image
4.4 存储器
- 存储器是计算机的存储部件,用来存放程序和数据。
- 存储器分为主存储器(主存,内存储器,内存)和辅助存储器(辅存,外存储器,外存)。
- CPU能够直接访问的存储器是主存。辅存用于帮助主存记忆更多信息,辅存中的信息必须调入主存后,才能被CPU访问。
- 主存包括存储体M、各种逻辑部件及控制电路等。
- 存储体由许多存储单元组成,每个存储单元包含若干存储元件(或称存储基元、存储元),每个存储元件存储一位二进制代码 0 or 1。
- 因此存储单元可存储一串二进制代码,称这串代码为存储字,称这串代码的位数为存储字长,存储字长可以是1B或是字节的偶数倍。一个存储字既可代表数,也可代表一串字符,也可代表指令等。
- 主存的工作方式为:按存储单元的地址进行存取,这种存取方式称为按地址存取方式,即按地址访问存储器(简称按地址寻访,访存)。
- 存储体存放二进制信息
- 地址寄存器(MAR)存放访存地址,经过地址译码后找到所选的存储单元。
- 数据寄存器(MDR)用于暂存要从存储器中读或写的信息,时序控制逻辑用于产生存储器操作所需的各种时序信号。
image
4.5 输入设备
- 输入设备的主要功能是将程序和数据以机器所能识别和接受的信息形式输入计算机。
- 常见的输入设备有键盘、鼠标、扫描仪、摄像机等
4.6 输出设备
- 输出设备的任务是将计算机处理的结果以人们所能接受的形式或其他系统所要求的信息形式输出
- 常用的输出设备有显示器、打印机等。计算机的I/O设备是计算机与外界联系的桥梁。
4.7 运算器
- 运算器是计算机的执行部件,用于进行算术运算和逻辑运算。
- 算术运算是按算术运算规则进行的运算,如加、减、乘、除;逻辑运算包括与、或、非、异或、比较、移位等运算。
- 运算器的核心是算术逻辑单元ALU(Arithmetic and Logical Unit)运算器包含若干通用寄存器,用于暂存操作数和中间结果,如累加器ACC,乘商寄存器MQ,操作数寄存器X,变址寄存器IX,基址寄存器BR等,其中ACC,MQ,X是必须有的。
- 运算器内还有程序状态寄存器PSW,也称标志寄存器,用于存放ALU运算得到的一些标志信息或处理机的状态信息。
1_4_7_image
05.如何学习组成原理
5.1 知识体系太大了
- 相较于整个计算机科学中的其他科目,计算机组成原理更像是整个计算机学科里的“纲要”。这门课里任何一个知识点深入挖下去,都可以变成计算机科学里的一门核心课程。
- 比如说,程序怎样从高级代码变成指令在计算机里面运行,对应着“编译原理”和“操作系统”这两门课程;计算实现背后则是“数字电路”;
- 如果要深入 CPU 和存储器系统的优化,必然要深入了解“计算机体系结构”。
5.2 如何学习该专栏
- 首先,学会提问自己来串联知识点。学完一个知识点之后,可以从下面两个方面,问一下自己。
- 我写的程序,是怎样从输入的代码,变成运行的程序,并得到最终结果的?
- 整个过程中,计算器层面到底经历了哪些步骤,有哪些地方是可以优化的?
- 以教带学的方式内化知识
- 无论是程序的编译、链接、装载和执行,以及计算时需要用到的逻辑电路、ALU,乃至 CPU 自发为你做的流水线、指令级并行和分支预测,还有对应访问到的硬盘、内存,以及加载到高速缓存中的数据,这些都对应着我们学习中的一个个知识点。
- 建议自己脑子里过一遍,最好是口头表述一遍或者写下来,这样对彻底掌握这些知识点都会非常有帮助。
- 写一些示例程序来验证知识点
- 计算机科学是一门实践的学科。计算机组成中的大量原理和设计,都对应着“性能”这个词。因此,通过把对应的知识点,变成一个个性能对比的示例代码程序记录下来,是把这些知识点融汇贯通的好方法。
- 因为,相比于强记硬背知识点,一个有着明确性能对比的示例程序,会在脑海里留下更深刻的印象。当你想要回顾这些知识点的时候,一个程序也更容易提示你把它从脑海深处里面找出来。
更多内容推荐
- GitHub:https://github.com/yangchong211
- 博客:https://juejin.cn/user/1978776659695784
- 博客汇总:https://github.com/yangchong211/YCBlogs
- 设计模式专栏:https://github.com/yangchong211/YCDesignBlog
- Java进阶专栏:https://github.com/yangchong211/YCJavaBlog
- 网络协议专栏:https://github.com/yangchong211/YCNetwork
- 计算机基础专栏:https://github.com/yangchong211/YCComputerBlog
- 系统性学习C编程:https://github.com/yangchong211/YCStudyC
- C++学习案例:https://github.com/yangchong211/YCStudyCpp
- Leetcode算法专栏:https://github.com/yangchong211/YCLeetcode
- Android技术专栏:https://github.com/yangchong211/YCAndroidBlog