【程序员必备小知识-基础】计算机体系结构

551 阅读6分钟

引言

  • 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。 现代计算机都是基于冯诺依曼体系结构建设的,包括:PC和服务器,这类体系结构组成的计算机由5大部分组成,分别是运算器、控制器、存储器、输入设备和输出设备、其中最主要的要属处理器和内存了,内存主要是用来存储数据和指令的,而处理器也就是我们的cpu,用来从内存中取指令执行的,常见的指令有:读写、运算等。

image.png

本篇文章作为一个小小的总结,以x86为例简要地梳理一下它们之间的关系。

内存与地址

生活当中我们都会遇到存取物品的情况,这里以蜂巢为例:快递员把物品放入箱体,然后会出一个码,你输入对应的码就能找到你存储物品的箱体,进而找到自己的物品。

image.png 内存也与此类似,内存会有多个存储单元对应我们的箱体,每个存储单元都会有一个地址对应箱体的码,箱体里的物品对内存而言,可能是数据或指令,不过一个地址所对应的存储单元不能是很多东西,而且只能存储一个字节,像int这样的数据保存要占多个地址,那以起始地址作为这个数据的地址。

内存地址是从0开始编号的整数,地址多大取决于cpu的最大地址空间,如果是32位的那就是从0x0000 00000xffff ffff

cpu

cpu至始至终只做一件事:取指令,然后解释执行,接着再取一条,再执行。 cpu主要包含以下功能单元:

  • 寄存器(Register):寄存器类似于内存,只不过比内存的访问速度更快,也叫高速存储器,x86的寄存器有如eax、eip、ebp等,不同的寄存器有不同的用途。
  • 程序计数器(PC):保存着cpu取指令的地址,cpu先从程序计数器中读取地址,然后拿着地址找到内存中的对应的指令,然后程序计数器的地址会自动加上该指令的长度,指向内存中的下一个指令地址。x86的程序计数器是特殊寄存器eip,地址是32位的,位数也是32位的,处理器的位数也叫字长。
  • 指令解码器(Instruction Decoder):指令解码器负责指令的解释执行,cpu拿到命令之后,解码器就开始进行命令的解析,因为命令也是由若干个字节构成,解码器看看哪些位表示内存地址,哪些位表示寄存器编号,哪些位表示读写运算操作,然后找到相应的执行单元进而执行它。
  • 算术逻辑单元(ALU,Arithmetic and Logic Unit):解码器解析出来的指令一看,操作是运算,ok,那就调动算数逻辑单元进行运算,运算结果可能保存在寄存器中,也可能保存到内存中。
  • 地址和数据总线(Bus):这可不是我们坐的公交车,不过要这么理解也对,cpu和内存之间要想互联互通,怎么也得有条路线吧,这个路线在计算机的世界里有三条:地址总线、数据总线和控制线,32位处理器对应32位的地址总线和数据总线,路通了,得发送信号了,这个信号在计算机内部是由01组成,然后每条线都可以是01,这样就有232次方可能,就用这个信号进行通信。 image.png

比如一个cpu向内存取数据的过程如下:

  1. 准备线路:cpu把寄存器的数据总线和传输数据总线对应好,等待接收数据
  2. 发送数据所在地址和控制:cpu将内存地址通过地址总线发送给内存,然后通过控制线发送了一个读请求。
  3. 内存处理:内存接收到地址和请求后,将对应的存储单元对应到传输数据总线的一端,然后存储单元的每一位就通过传输数据线到达了寄存器上。

image.png

设备

与计算机相关的设备有输入设备、输出设备、还有运行存储设备,拿输入设备为例,你在键盘输入一个字,这个字就显示在屏幕上,如果没有cpu的参与是不可能成功的,那设备是如何和cpu打交道的呢?

image.png

CPU的角度来看,访问设备只有内存映射I/O和端口I/O两种,要么像内存一样访问,要么用一种专用的指令访问。由于计算机的设备五花八门,各种设备的性能要求都不一样,于是出现了各种适应不同要求的设备总线,比如PCI、AGP、USB、1394、SATA等等,这些设备总线并不直接和CPU相连,CPU通过内存映射I/O或端口I/O访问相应的总线控制器,通过它再去访问挂在总线上的设备。

我们写的程序是存储在硬盘上的,但在x86平台上,硬盘是ATA、SATASCSI总线上的设备,不和cpu直接相连,因此操作系统就会先将其拷到内存上,然后被cpu取指令执行,这个过程我们也称为加载(Load)。程序加载到内存之后,操作系统就把这些需要调度执行的任务进行分片,每个片都会被cpu执行一段时间,这个片就称为进程(Process),由于cpu执行速度非常快,所以在肉眼看起来就是多任务同时执行。

访问设备还有一点与内存不同,就是内存是被动的等待cpu的访问,但设备不同,设备是主动产生数据和动作的,比如你用输入了一个字母,你希望cpu赶快响应,然后设备主动通知cpu完成这个字符的响应,这一机制称为中断。我们Linux也提供了一些类似中断的指令:比如常见的中断命令的指令Ctrl+C,中断键盘输入的指令Ctrl+D等等。

image.png

由于各种设备的用途各不相同,设备寄存器中每个位的定义和操作方法也各不相同,所以每种设备都需要专门的设备驱动程序(Device Driver),一个操作系统为了支持广泛的设备就需要有大量的设备驱动程序,事实上,Linux内核源代码中绝大部分是设备驱动程序。设备驱动程序通常是操作系统内核里的一组函数,主要是通过对设备寄存器的读写实现对设备的初始化、读、写等操作。