计算机中CPU、内存、硬盘、指令的的作用以及运行浅析

来源:互联网 发布:js动态添加class样式 编辑:程序博客网 时间:2024/06/04 19:41

最近在学习计算机的基本原理和组成,讲自己的学习的一点东西在博客上做一个记录。

一、冯诺依曼结构:

现在的计算机都是冯诺依曼结构的,根据wiki的定义冯诺依曼的结构如下:

这里写图片描述

主要由内存、运算+控制(CPU)、输入和输出设备组成。在上图中把 控制单元和逻辑计算单元分开了,其实在现实中都是由CPU来完成的。内存就是平时我们说的内存,看下wiki上的解释,即主存RAM,RAM的几个特点如下:

  1. 随机储存;
    所谓“随机存取”:指的是当存储器中的消息被读取或写入时,所需要的时间与这段信息所在的位置无关。相对地,有串行访问存储器包括顺序访问存储器(如:磁带)和直接访问存储器(如:磁盘)。
  2. 易失性:当电源关闭时RAM不能保留数据。如果需要保存数据,就必须把它们写入一个长期的存储设备中(例如硬盘)。RAM和ROM相比,两者的最大区别是RAM在断电以后保存在上面的数据会自动消失,而ROM则不会。
  3. 较高的访问速度:现代的随机存取存储器几乎是所有访问设备中写入和读取速度最快的,访问延迟也和其他涉及机械运作的存储设备(如硬盘、光驱)相比,也显得微不足道。但速度仍然不如作为CPU缓存用的SRAM。
  4. 需要刷新:现代的随机存取存储器依赖电容器存储数据。电容器充满电后代表1(二进制),未充电的代表0。由于电容器或多或少有漏电的情形,若不作特别处理,电荷会渐渐随时间流失而使数据发生错误。刷新是指重新为电容器充电,弥补流失了的电荷。DRAM的读取即有刷新的功效,但一般的定时刷新并不需要作完整的读取,只需作该芯片的一个列(Row)选择,整列的数据即可获得刷新,而同一时间内,所有相关记忆芯片均可同时作同一列选择,因此,在一段期间内逐一做完所有列的刷新,即可完成所有存储器的刷新。需要刷新正好解释了随机存取存储器的易失性。
  5. 对静电敏感:正如其他精细的集成电路,随机存取存储器对环境的静电荷非常敏感。静电会干扰存储器内电容器的电荷,引致数据流失,甚至烧坏电路。故此触碰随机存取存储器前,应先用手触摸金属接地。

常见的硬件设备还有硬盘(HDD)当然还有最近也慢慢开始流行的固态硬盘(SDD),SDD的速度比HDD要快上好几倍,
下面看下wiki上硬盘的介绍:

硬盘是电脑上使用坚硬的旋转盘片为基础的非挥发性存储设备,它在平整的磁性表面存储和检索数字数据,信息通过离磁性表面很近的磁头,由电磁流来改变极性方式被电磁流写到磁盘上,信息可以通过相反的方式读取,例如读头经过纪录数据的上方时磁场导致线圈中电气信号的改变。硬盘的读写是采用随机存取的方式,因此可以以任意顺序读取硬盘中的数据。硬盘包括一至数片高速转动的磁盘以及放在执行器悬臂上的磁头。

CPU:就是我们常说的中央处理器,看下wiki上的简介,

中央处理器(英语:Central Processing Unit,缩写:CPU),是计算机的主要设备之一,功能主要是解释计算机指令以及处理计算机软件中的数据。计算机的可编程性主要是指对中央处理器的编程。中央处理器、内部存储器和输入/输出设备是现代电脑的三大核心部件。1970年代以前,中央处理器由多个独立单元构成,后来发展出由集成电路制造的中央处理器,这些高度收缩的组件就是所谓的微处理器,其中分出的的中央处理器最为复杂的电路可以做成单一微小功能强大的单元。

根据以上专业性、术语性比较强的描述我们可以知道,CPU是用来执行指令和处理大规模计算的控制和运算单元,硬盘则是可以永久性的储存信息的信息储存设备,但是硬盘的读写速度比CPU慢的太多,内存就是为了解决CPU直接访问硬盘速度过低而产生的,在这里要介绍一个概念:程序的局部性原理,以下是百度百科的定义:

程序的局部性原理是指程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分。相应地,执行所访问的存储空间也局限于某个内存区域。局部性原理又表现为:时间局部性和空间局部性。时间局部性是指如果程序中的某条指令一旦执行,则不久之后该指令可能再次被执行;如果某数据被访问,则不久之后该数据可能再次被访问。空间局部性是指一旦程序访问了某个存储单元,则不久之后。其附近的存储单元也将被访问。
所以根据程序的局部性原理(时间局部性和空间局部性),CPU访问的资源会集中在某一区域,那么将这些资源从硬盘中放置到内存中,方便CPU进行访问,可以极大程度的提升访问资源的速度,以加快程序的运行。

我们现在都是使用的存储程序计算机,存储程序计算机在体系结构上主要特点有:

  1. 以运算单元为中心
  2. 采用存储程序原理
  3. 存储器是按地址访问、线性编址的空间
  4. 控制流由指令流产生
  5. 指令由操作码和地址码组成
  6. 数据以二进制编码

那么指令又是什么呢,根据wiki的定义:

指令在计算机技术中,“指令”是由指令集架构定义的单个的CPU操作。在更广泛的意义上,“指令”可以是任何可执行程序的元素的表述,例如字节码。
在传统的构架上,指令包括一个操作码(opcode)——它指定了要进行什么样的操作,例如“将存储器中的内容与寄存器中的内容相加”——和零个或者更多的操作数(operand)——它可能指定了参与操作的寄存器、内存地址或者立即数(literal data)。操作数可能还包括寻址方式,它确定了操作数的含义。
构成程序的指令很少以它在机器内部的数值形式而直接的被使用;它们可以被程序员通过汇编语言加以表示,或者,更常见的,被编译器生成。

那么可以看出指令就是可以让CPU最小单元来执行一个操作的命令,指令一般由操作码和地址码构成,操作码表明了需要进行什么操作,地址码来取到相应地址的值,一般指令的常见形式有汇编等。

二、以C语言中的helloworld为例来说明,到底计算机中发生了什么

我们刚开始接触计算机编程的时候,大多数学校都是以C作为启蒙教程的,那么我们看下C语言中的helloworld:
hello.c

#include<stdio.h>int main(){    printf("hello, world\n");}

其中#include<stdio.h>表示加载标准的C语言中的IO输出.h头文件,为后面使用printf铺垫,后面的int main()是这个程序中的主函数,一个C语言程序中只有一个主函数。
打开一个编辑器(例如VIM)在编辑器中输入以上的程序,然后进行保存,此时这个文件已经被保存在硬盘上了,而这个hello.c也被我们称作源文件。现在打大部分操作系统都是使用ASCII码来表示文本字符的,就是用一个唯一的单字节大小的整数值来表示每个字符,源程序中每个字节会对应于一个ASCII码值。
在这个程序可以运行之前,会经过四个阶段:

  • 预处理阶段:预处理器根据字符#开头的命令,将hello.c中的第一行#include<stdio.h>告诉预处理器读取系统头文件stdio.h中的内容,把它直接插入到程序文本中,得到了另一个C语言程序hello.i(通常是以.i文件作为拓展名);
  • 编译阶段:编译器将hello.i翻译成文本文件hello.s,它包含了一个汇编语言程序,汇编程序中的每一条语句都以一种标准的文本确切的描述了一条低级的机器语言指令。看下wiki中汇编的描述:

    汇编语言(英语:assembly language)是一种用于电子计算机、微处理器、微控制器,或其他可编程器件的低级语言。在不同的设备中,汇编语言对应着不同的机器语言指令集。一种汇编语言专用于某种计算机系统结构,而不像许多高级语言,可以在不同系统平台之间移植。
    使用汇编语言编写的源代码,然后通过相应的汇编程序将它们转换成可执行的机器代码。这一过程被称为汇编过程。
    汇编语言使用助记符(Mnemonics)来代替和表示特定低级机器语言的操作。特定的汇编目标指令集可能会包括特定的操作数。许多汇编程序可以识别代表地址和常量的标签(Label)和符号(Symbols),这样就可以用字符来代表操作数而无需采取写死的方式。普遍地说,每一种特定的汇编语言和其特定的机器语言指令集是一一对应的。

  • 汇编阶段:汇编器将hello.s翻译成机器语言指令,并将这些指令打包为一种称为可重定位目标程序的格式,并将结果保存在目标文件hello.o中,hello.o是一个二进制文件,它的字节编码是机器语言指令而不是字符。

  • 链接阶段:hello程序调用了printf函数,printf函数存在于一个叫printf.o单独的预编译好的目标文件中,这个文件必须合并到我们的hello.o程序中。链接器就负责处理这种合并,最后得到hello文件,它是一个可执行文件,可以被加载到内存中,由系统执行。

    由以上可以看出,硬盘负责存储我们的源文件,然后经过编译和汇编(是一系列的机器语言指令)之后,会在内存中开辟相应的空间,将源文件通过汇编翻译为机器语言后,在内存中通过相应的地址和操作,CPU负责进行逻辑控制和计算,最后通过Output设备进行输出,当然在最开始的时候我们通过键盘和鼠标录入就是通过Input设备进行输入。
    对于汇编成为机器指令的详细过程,目前还不是特别懂,感兴趣的同学可以查看《编译原理》,提供一个GitHub的下载地址。
    以上很多内容是借鉴《深入理解计算机系统》,不足之处,大家尽情吐槽,尽情拍砖。

0 0