计算机组成
1.计算机的总线
总线就是连接计算机不同设备的一条数据线,这里强调是“一条”。作用是解决不同设备间的通信问题,而且可以简化计算机内部电路的复杂度。
为什么强调总线是一条,因为总线可以连接计算机所有的设备,使得计算机所有设备都可以通信。
例如:
存储器
控制器
运算器
输入设备
输出设备
如果不用总线将这5个部分连在一起,那么存储器和输入设备通信要在他们之间连一条线,控制器和输出设备同信也要在他们之间连一条线。谁和谁之间要进行同信就要在他们之间连一条线造成线路复杂。而总线将所有设备连在一起就可以让所有设备两两同信,大大简化了电路。
当然计算机内并不是真的只有一条线,只不过是为了形象描述总线才这样说。
例如
USB : universal serial bus ,通用串行总线
这是一种通用的针对外部设备连接的总线,不同设备可以通过USB接口连接。
例如鼠标,键盘,u盘,USB是一种规范,规定了所有外部设备都要使用这种接口和总线才能和计算机连接
除了USB总线,还有PCI总线,ISA总线等...
总线的分类
片内总线,即一个芯片内部的总线(高集成芯片内部的信息传输线)。例如CPU中的总线会连接寄存器和寄存器,寄存器和控制器、运算器
系统总线,总线是连接CPU,主内存,IO设备等独立组件之间的总线。
又可以分为 数据总线,地址总线,控制总线
数据总线和CPU的位数相同(32/64位)
如果是32位的总线,该总线一次可以传输 4个字节的数据。64位总线一次可以传输8个字节的数据
所以可以将总线的位数理解为是其宽度。
数据总线是可以双向传输的。
地址总线是传输源数据和目的数据在内存中的地址的总线,用于数据的寻址
地址总线位数=n,寻址范围是0~2^n
控制总线是用于发送各种控制信号的传输线
控制信号由一个组件设备发送到另一个组件设备
控制总线可以监视不同组件间的状态(就绪/未就绪)
总线仲裁
总线仲裁是为了解决总线使用权的冲突问题。
总线的仲裁有3中方法
链式查询:相当于一个串联电路,假设有3个设备,他们会与仲裁控制器进行一个有顺序的串联,离仲裁控制器近的设备其优先级更高。
好处:电路复杂度低,仲裁方式简单
坏处:低优先级的设备难以得到电路使用权
而且对电路故障敏感
计时器定时查询:仲裁控制器会对设备编号并使用计数器累计计数
独立请求:每一个设备都会单独连接仲裁控制器,向它同时发出要使用总线的请求。仲裁控制器决定谁先试用总线
2. 计算机的输入输出设备
常见的输入输出设备
输入设备分为:字符输入设备(键盘)和图像输入设备(鼠标,扫描仪,数位板)
输出设备:显示器,打印机,投影仪
输入输出接口的通用设计
数据线,状态线,命令线,设备选择线,
CPU和IO设备的通信方式
两种:程序中断和DMA(直接内存访问)
首先CPU的速度和IO设备的速度不一致,查了10倍到100倍甚至以上
程序中断:例如鼠标接入时会发出一个中断信号,CPU会停止主程序运行响应这个中断,做一些发送数据给接入设备之类的操作,然后CPU继续主程序运行,而鼠标也可以正常使用
程序中断为低速设备提供了一种异步通知CPU的方式
但是频繁打断CPU的工作会影响效率
DMA:IO设备和主内存通过DMA设备连接,当主存和IO设备交换消息时直接通过DMA,无需中断CPU。意思是CPU不会参与IO操作,IO设备和内存的交互通过DMA完成的,也就是说是DMA设备完成IO操作的。如果让CPU参与IO操作,会由于CPU和IO设备的速度不一致让CPU等待很久,CPU就无法处理程序和进行运算。一句话,CPU是用来运算的而并不是进行IO操作的。
但是IO设备和主存交换数据的过程,CPU也不是完全不参与。CPU会向IO设备发出请求,如请求将磁盘中的数据写入内存。DMA就会接受请求,由DMA完成主存和磁盘的数据交换(磁盘数据写入主存或者主存数据写入磁盘),而这个过程CPU不参与。
例如 硬盘,显卡就是使用DMA来通信的。
3. 计算机存储器
存储器就是如内存,U盘,固态硬盘之类存储数据的设备
按照存取方式分类分为
随机存储器(RAM):可以随机读取(读取的顺序是随机的,可以不按照写时的顺序读取),和位置无关
串行存储器:按写时顺序查找,和位置有关
只读存储器:只读不写
存储器的层次结构
买储存器要考虑读写速度,存储内容和价格
容量+价格 -> 位价 位价是每比特位的价格,用于衡量硬盘性价比
存储器分3个层次
缓存:如CPU寄存器和高速缓存,容量小,速度快价格高
主存:即内存,速度适中,容量中,价格中
辅存:即硬盘,u盘等,速度慢,容量大,价格低
CPU,缓存和主存三者是可以两两直接通信的,属于为缓存-主存层次。
原理:局部性原理
实现:通过在CPU和主存之间增加一层速度快(容量小)的cache(高速缓存)。
目的:解决主存和CPU速度不匹配的问题(CPU处理速度比内存读写要快)。系统会将CPU要访问的内存数据尽可能的放到缓存中,CPU可以直接从缓存中获取这部分数据而无需在较慢的内存中获取。
局部性原理指:CPU访问存储器(内存和缓存)时,无论存取指令还是存取数据,所访问的内存存储单元都趋于聚集在一个较小的连续区域中(内存是分成一小块一小块的,而存储的数据是多个块连在一起的而不是分散在不相邻的块中)。
而辅存只能和主存直接通信,无法和CPU以及缓存直接通信,属于主存-辅存层次。所以将数据存入辅存(硬盘),数据要先经过主存。
原理:局部性原理
实现:在主存之外增加辅助存储器(磁盘,SD卡,U盘等)
目的:扩容
缓存的存在是为了解决CPU和内存速度不一致的问题,解决的是速度问题
辅存的存在是为了解决内存容量不足的问题,解决的是容量的问题
主存和辅存
为什么计算机断电,内存数据会丢失,而辅存数据不会消失。
主存是属于RAM(随机存取存储器)。RAM通过电容存储数据,每隔一段时间刷新一次,所以断电会导致无法刷新而丢失数据。
结论就是:主存属于RAM,所以断电会导致数据丢失。
CPU和内存可以直接通信是因为CPU内包含主存数据寄存器(MDR)和主存地址寄存器(MAR)。
CPU的主存地址寄存器通过地址总线和主存连接,主存数据寄存器通过数据总线和主存连接。所以CPU能指定数据在内存的位置并传输数据到内存。
结论就是:CPU的寄存器和内存之间有总线连接,CPU的寄存器中保存着内存块的地址,所以CPU可以和内存直接通信。
位数和内存的关系:
32位系统即使插入再多的内存条也最多只有2^32=4*2^30=4GB的内存。因为32位系统最多只有2^32个地址,而一个地址指向的空间的大小是1byte,所以 一个空间1byte * 4G个空间=4GB(寻址范围有限)
64为系统最多可以有2^64=2^30*2^34=1G * 2^34=2^34G 个地址,每个地址的空间大小1byte,所以最多可容纳 2^34GB的空间
高速缓存
高速缓存是为了解决CPU和主存速度不匹配的问题
在此之前先介绍内存的一些基本概念:
位,字节和内存结构
已知CPU不能直接访问硬盘数据,只能通过将硬盘数据加载到内存再从内存读取数据。
内存中有海量的小格子,一个格子只能存1个bit,也就是说一个格子只能存一个二进制位(0或者1)
但是内存中的格子数有海量多个,如果CPU要从内存中读取某一个数据不可能一个个格子遍历。
所以内存会将8个bit排成1组,每一组为1个单位,也就是1字节。
CPU不能访问某个位,只能访问某1个字节字节。
所以1byte就是内存最小的IO单位。
内存地址
每一个基本内存空间(一个字节)都有一个内存地址
一个地址指向一个字节空间
地址的表现形式为32位或者64位的二进制,可以理解为一个地址是一个key,一块内存空间中存的值是一个value
一个地址能够指向的内存空间是一个字节那么大的空间,即一个内存地址指向一个字节。
例如在32位系统中:
内存地址 指向 内存空间
0FF0F0F0(地址) 01101100(值)
0FF0F0F0表示为2进制是 00001111111100001111000011110000 (32个位的地址)
这个地址指向01101100这个值所在的空间
当然计算机如果要找到一块多字节的较大空间的位置,他会去找这个多字节空间的第一个字节所在的内存地址。当然这块较大的空间内的每一个字节都有一个内存地址。
系统是多少位的,内存地址的长度就是多少位(32位或者64位)。
操作系统位数
操作系统位数指的是CPU一次能处理的最大位数的数据,如64位系统一次能处理64位=8byte的数据
操作系统的位数决定计算机内能存储的二进制的位数上限。也决定着内存地址的位数上限和个数上限。
例如 32位系统的内存地址长度为32位。
所以内存地址最多只有 2^32 个。
由于一个内存地址指向一个字节,所以操作系统最多有2^32个字节的内存空间就是 2^32byte = 4GB
所以这就是为什么说 32位系统只能最多有4G的内存。即使给32位系统装上8G内存条(2^33个byte),系统也只能给其中的4G内存(给其中的2^32个byte)分配地址。剩余4G内存是没有地址的。
64位系统中内存地址都是64个位的长度。
可以给 2^64 个byte = 2^34 G的空间分配地址。所以计算机可以容纳的最大内存量为2^34个GB
指针
指针就是用来存放内存地址的,指针的内容就是内存地址;也可以说指针就是内存地址
内存的一个最小空间可以存1个byte的数据
而内存地址也需要用一个内存空间存储。
在32位系统,内存地址是一个32位的二进制,所以要用一个32/8=4字节的内存空间才能存下一个地址,所以一个指针的长度为4
在64位系统,内存地址是一个64位的二进制,所以要用一个64/8=8字节的内存空间才能存下一个地址,所以一个指针的长度为8
内存中的字和字块
字:计算机进行数据处理时,一次存取、加工和传送的数据长度称为字(也是CPU一次操作能处理的数据量)
一个字由一个或者多个字节组成
字长就是一个字有多少个位,计算机的字长决定了其CPU一次操作处理实际位数的多少(所以一个字的字长等于操作系统的位数),由此可见计算机的字长越大,其性能越优越。在32位系统中,一个字的字长为32位=4字节;64位系统一个字的字长=64位=8字节
字节是计量单位,而字是其用来一次性处理事务的一个固定长度的单位。
字块:存储在连续的存储单元中被看做是一个整体的一组字(一组连续的字组成一个字块)。
字和字块可以理解为是存储数据的容器。字是CPU一次性能处理的数据量,而字块是多个字组合而成的一个大一点的容器。
字和字块是容器,所以字和字块可以存储数据
字块内的字的存储是连续的,所以一个字块中的所有字可以看成一个整体。而不同的字块间是独立的个体。
字块就像是一个房子,而字就像这个房子中的房间。房子和房子之间是独立的,而房子内的所有房间是相连相通的(字块内的字是连续的)。
内存是由很多的字块组成的一个更大的存储容器,所以内存像多个房子组成的一栋大楼。
字符串和内存地址的关系:
已知一个英文字母是一个字节8个位,所以一个英文字母刚好可以只占了一个内存地址和一个最小的内存空间单位
一个gbk编码的字符串有2个字节,要占2个能寻址的最小内存空间
例如一个"我"字,数据内容为
01100010 00010001
地址A 地址B
此时两个地址分别指向两个字节空间
但是"我"字的地址是开头的地址A而不是B
总结:
字节是计算机中最小的能被分配地址的存储单位,一个内存地址指向一个字节
内存地址是内存当中存储数据的一个标识,并不是数据本身,通过内存地址可以找到内存当中存储的数据。
操作系统位数是CPU一次能处理的最大位数的数据,也是一个字的大小。
在32或64位系统中,内存地址的位数为32或64
字是由一个或者多个字节组成,字长由系统位数决定
另外不仅仅是内存中的空间有地址,硬盘,高速缓存等,只要是存储器的空间都会有地址
字的寻址:
想要找到内存中某一个字的位置,就要知道2个地址:
这个字所属字块在内存中的地址(也叫块地址)
这个字在该字块中的地址(也叫块内地址)
无论是块内地址还是块地址都表示为二进制。
地址用多少位表示取决于这块内存有多少个字块以及每个字块有多少个字,以及每个字有多少位。
假如一个字有32位,一个字块有B个字,主存中拥有M个字块。
主存的总字数 = B*M
主存的总容量 = 32*B*M 个bit
具体例子:
主存空间4G,字块大小4M,字长32位,问此时块地址和块内地址的位数为多少。
块的个数= 4G/4M = 1024 所以块地址的最大值用十进制表示为1024,用二进制表示为2^10,所以块地址的位数应为10位,应该用10位的2进制来表示该计算机的块地址
每个块的字个数 = 4M / 32bit = 4M/4byte=1024^2=2^20,所以块内地址要用20位的2进制表示块内地址
所以,块地址和块内地址的位数为 10 和 20
假如第100个块的第1000个字的地址为:
块地址:0001100100
块内地址:00000000001111101000
回到高速缓存
高速缓存的结构和主存一样,也是由字和字块组成。
高速缓存的字块数远小于主存的字块数,所以主存的容量要比缓存大。
高速缓存的数据来自于主存,高速缓存的字块是主存中字块的一个复制,通过复制主存中字块的数据到高速缓存的字块中达到的。
缓存的速度比主存更快
如果CPU需要的数据在缓存就会去缓存中取
如果CPU需要的数据不在缓存中就会去主存中取
CPU访问主存比访问缓存的速度慢
CPU访问到缓存而不去访问主存的概率叫做命中率
命中率是衡量缓存的重要性能指标
假如CPU有10次在高速缓存中取数据,20次在主存取数据,命中率=33%
良好的缓存替换策略有助于提高缓存的命中率
高速缓存的替换时机和策略
高速缓存的替换时机:当CPU所需要的的数据不在高速缓存中时,CPU会从内存中取数据,同时会将这部分数据存入到高速缓存中(换个说法,CPU要读取某个地址的数据,如果缓存没有这个地址就会从内存找,并将这个地址的数据放到缓存,下次如果CPU还是访问这个地址就直接从缓存读)。但是如果高速缓存容量满了,就会将缓存中的旧数据(字块)替换为从主存获取的新数据(字块)
所以替换时机有两个: 1 高速缓存容量满了; 2 CPU使用到高速缓存中没有的数据
替换策略有
1 随机算法
随机将缓存中的某字块替换为新字块
2 先进先出算法(FIFO)
缓存中的所有字块按照存入缓存的先后顺序放到一个队列中,当要替换字块的时候,最先存入的旧字块从头部被pop出队列,新字块被push入队列尾部
3 最不经常使用算法(LFU)
缓存会单独开出一块空间用于存储每一个字块被CPU调用的次数,类似于map的数据结构,如下
字块 A B C D E
次数 5 3 1 4 2
当需要替换数据的时候,会找到调用次数最少的C,将C字块换成新的字块
4 最近最少使用算法(LRU)
该算法中缓存的字块会放入一个双向链表中
此时,CPU使用了高速缓存的某一个字块,这个字块会放到链表头部。当CPU使用到主存的字块,主存的字块会放到链表头部并将链表尾部的字块删除
例如
A B C D E F
当CPU使用到C字块:
C A B D E F
当CPU使用到B字块:
B C A D E F
当CPU使用到S字块:
S B C A D E (F被删除)
计算机的指令系统
机器指令
是CPU能直接识别并执行的指令。我们常说CPU的作用是逻辑运算和处理数据,其实CPU是通过执行机器指令来完成运算操作的。
机器指令有两部分组成:操作码和地址码(或者直接就是操作数)
机器指令: 操作码|地址码
操作码是一个代码
操作码指明这个机器指令要完成的操作
操作码的位数反映了这个计算机的操作种类有多少,例如操作码是一个8位的二进制,这个计算机就共有2^8=256种操作码,可以对数据进行256中操作。
操作数
操作数是操作的对象,就是要操作和运算的数据。
要被处理的数据(操作数)如果比较小,可以直接放在机器指令中,此时指令中就无需地址码。如果操作数会比较大,是不能直接放在机器指令中而是放在内存或者缓存存储的。此时就需要在机器指令中记录这个操作数的空间地址,这个就是地址码。
操作指令可以根据地址码在缓存或者内存空间中找到操作数从而进行运算。
机器指令分为:三地址指令,二地址指令,一地址指令和零地址指令
三地址指令是机器指令中有3个地址码,如
操作码|addr1|addr2|addr3
一般是addr1的数据和addr2的数据进行操作码指定的操作,将操作后的结果放到addr3的空间中。
例如 C = A+B (以加法操作为例)
二地址指令是机器指令中有2个地址码(废话),如
操作码|addr1|addr2
一般是addr1的数据和addr2的数据进行操作码指定的操作,将操作后的结果放到addr1或者addr2的空间中。
例如 A=A+B
一地址指令:
操作码|addr1
一般是addr1的数据进行操作码指定的操作,将操作后的结果放到addr1的空间中。
例如 A++(以自增操作为例)
零指令操作是机器指令中没有地址码的指令
如空操作,停机操作,中断返回操作等
PS:
机器指令就是保存在寄存器,缓存和内存中的。要执行的指令会放在寄存器中,而寄存器中的指令其实也是从缓存,内存中取得的。
寄存器,顾名思义,寄存就是暂存的意思,它就是一个临时放指令,地址和数据的空间(指令中就包含地址和一些不大的数据)。
按与CPU远近来分,离得最近的是寄存器,然后缓存,最后内存。
CPU会从寄存器中读取指令来执行。
机器指令的操作类型
1.数据传输操作:
如寄存器之间、寄存器与存储单元(磁盘内存缓存)、存储单元和存储单元间的数据传输
数据读写,交换地址,清零置一等操作
2.算数逻辑操作:
加减乘除
或,且
3.移位操作:
数据左移(乘2)、数据右移(除2)
4.控制指令:
等待指令,停机指令,空操作,中断返回
机器指令的寻址方式
指令寻址
包括顺序寻址和跳跃寻址
例如CPU的寄存器中有一串命令:
地址 指令
101 MOV R0,R1 # MOV 是操作码,R0和R1是操作数在内存中的地址
102 LAD R1,6
103 ADD R1,R2
104 AND R1,R3
105 JMP 102 # 跳回102
从101到105就是顺序寻址,105跳回102是跳跃寻址
数据寻址
包括立即寻址,直接寻址,间接寻址
立即寻址就是,机器指令中直接存着操作数,不用去寻址
直接寻址是机器指令中存着操作数的地址,根据这个地址,可以在内存中找到操作数所在的空间,然后指令就能获取这个操作数并进行运算。
间接寻址是机器指令存着一个地址,根据这个地址,可以在内存中找到一个空间,这个内存空间中存的还是一个地址,再根据这个地址才能在内存中找到操作数所在的空间。
数据寻址 优点 缺点
立即寻址 速度快 地址码的位数限制操作数表示范围
直接寻址 寻找简单 地址码的位数限制寻址范围
间接寻址 操作数寻址范围大 速度慢
=============================================
CPU
CPU包括但不限于 运算器,控制器,高速缓存等
CPU的控制器:用于协调和控制计算机运行
控制器包括程序计数器,时序发生器,指令译码器,各类寄存器(指令寄存器,主存地址寄存器,主存数据寄存器,通用寄存器),总线
所以寄存器是属于CPU控制器的一部分
程序计数器
在CPU中,每一条机器指令都有一个地址,程序计数器用于存储CPU要执行的下一条指令的地址
时序发生器
用于发送时序脉冲(控制CPU运算的节奏)
指令译码器
翻译操作码为对应的操作(分析指令)
指令寄存器
从主存或缓存中获取机器指令,并暂存这些机器指令。CPU就可以直接从寄存器获取指令,不用到主存或者缓存中取。所以寄存器是保证CPU运行效率的一个重要结构
主存地址寄存器
保存CPU马上要访问的内存空间地址
主存数据寄存器
保存CPU正要读或写的主存数据
通用寄存器
暂时存放指令或数据
保存ALU运算的中间结果
容量比前面三个寄存器大
寄存器是通过总线和内存交互数据的
CPU的运算器 :用于数据运算
包括 数据缓冲器,ALU,通用寄存器,状态字寄存器,总线
数据缓冲器:分为输入缓冲和输出缓冲
输入缓冲暂时存放外设送过来的数据
输入缓冲暂时存放送往外设的数据
缓冲顾名思义,就是不直接将要传输的数据一个个的传送,而是把要传输的数据先存起来,存到一定量之后一次性传送。
ALU : 算数逻辑单元。是运算器的主要部分。
可以完成位运算和加减乘除等运算。
也就是说,CPU的运算功能就是来自于ALU
下面是ALU的大致样子
状态字寄存器:存放运算状态
通用寄存器:同上
指令执行过程:
取指令 -> 分析指令 -> 执行指令
先列出所有设备:
运算器:ALU,寄存器,数据缓冲器,状态字寄存器
控制器:程序计数器,指令译码器,时序发生器,指令寄存器
高速缓存:数据缓存,指令缓存
这些设备使用过片内总线连起来的。
首先数据和指令会被缓存在数据缓存和指令缓存中。
接下来程序计数器会记录要执行的指令的地址(如 101)
程序计数器只记录了指令的地址,但是不知道指令的内容,所以会通过总线在指令缓存中获取指令内容。
将获取到的指令内容存到指令寄存器中(如 MOV R0,R1)
现在这个指令还是不能被运算器识别的,指令寄存器会将指令传到指令译码器来翻译这个指令。
指令译码器会发出控制信号,把被翻译的指令发送到运算器中的ALU来进行运算。同时程序计数器会记录下一条要执行的指令的地址(101变成102)
ALU处理完数据会记录运算状态,送出运算结果。
整个指令执行过程:
取指令 -> 分析指令 -> 执行指令
(从缓存取指令) (指令译码器译码) (装载数据到寄存器)
(送到指令寄存器) (发出控制信号) (ALU处理数据)
(程序计数器+1) (记录运算状态)
(送出运算结果)
CPU的流水线设计
从上面的流程中,控制器负责取指令和分析指令,运算器执行指令。是一个顺序执行的过程(串行),这样CPU的效率不高。
所以这里提出了CPU流水线,其实就是让取指令,分析指令和执行指令并行。