计算机系统概述
前言
计算机系统是计算机硬件和系统软件组成的,它们共同工作来运行应用程序。其中系统软件包括操作系统和应用程序。

操作系统是来管理硬件的,操作系统有两个基本功能:
(1)防止硬件被失控的应用程序滥用;
(2)向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。
计算机硬件
冯诺依曼模型
定义计算机基本结构为 5 个部分,分别是运算器、控制器、存储器、输入设备、输出设备,这 5 个部分也被称为冯诺依曼模型。

1总线
总线是用于 CPU 和内存以及其他设备之间的通信,总线可分为 3 种:
- 地址总线,用于指定 CPU 将要操作的内存地址;
- 数据总线,用于读写内存的数据;
- 控制总线,用于发送和接收信号,比如中断、设备复位等信号,CPU 收到信号后自然进行响应,这时也需要控制总线;

当 CPU 要读写内存数据的时候,首先要通过「地址总线」来指定内存的地址;然后通过「控制总线」控制是读或写命令;最后通过「数据总线」来传输数据;
2 IO设备
输入设备向计算机输入数据,计算机经过计算后,把数据输出给输出设备。期间,如果输入设备是键盘,按下按键时是需要和 CPU 进行交互的,这时就需要用到控制总线了。
3 处理器CPU

处理器由PC(程序计数器)(控制单元)、ALU(逻辑计算单元)、寄存器文件和总线接口(存储单元)组成。另外CPU的位宽指的是一次最大能处理的数据长度。
以在shell终端运行为例,如下图
-
从键盘上读取hello命令
![image-20220618200523864]()
感觉读写输入缓存区和程序中的表达式计算值及函数返回中间值都是放在寄存器文件里面的
-
从磁盘加载可执行文件到内存
![image-20220618200657848]()
程序指令和相应定义的数据都存储在主存,处理器只会读取命令,执行命令时读取相应数据。
-
将输出字符串从存储器写到显示器
![image-20220618200825762]()
4 内存
我们的程序和数据都是存储在内存,存储的区域是线性的。计算机最小的存储单位是字节(byte),1 字节等于 8 位(8 bit)。每一个字节都对应一个内存地址。
存储器设备层次
主要存储器
-
随机访问存储器(以字节为单位读写,读取事件与数据所在位置无关)(断电数据消失)
- 静态RAM主要用于高速缓存
- DRAM用作主存以及图形系统的帧缓冲区
-
非易失性存储器(用来存储一般性数据)
非易失性存储器(nonvolatile memory)即使是在关电后,仍然保存着它们的信息。现在有很多种非易失性存储器。由于历史原因,虽然ROM中有的类型既可以读也可以写,但是它们整体上都被称为只读存储器(Read-Only Memory, ROM)。ROM是以它们能够被重编程(写)的次数和对它们进行重编程所用的机制来区分的。
-
PROM
只能被编程一次。PROM的每个存储器单元有一种熔丝(fuse),只能用高电流熔断一次。
-
可擦写可编程ROM (EPROM)
可擦写可编程ROM(EPROM)有一个透明的石英窗口,允许光到达存储单元。紫外线光照射过窗口,EPROM单元就被清除为0。对EPROM编程是通过使用一种把1写人EPROM的特殊设备来完成的。EPROM能够被擦除和重编程的次数的数量级可以达到1000次。电子可擦除PROM(EEPROM)类似于 EPROM,但是它不需要一个物理上独立的编程设备,因此可以直接在印制电路卡上编程。EEPROM能够被编程的次数的数量级可以达到10次。
-
闪存
闪存(flash memory)是一类非易失性存储器,基于EEPROM,它已经成为了一种重要的存储技术。闪存无处不在,为大量的电子设备提供快速而持久的非易失性存储,包括数码相机、手机、音乐播放器、PDA和笔记本、台式机和服务器计算机系统。在6.1.3,节中,我们会仔细研究一种新型的基于闪存的磁盘驱动器,称为固态硬盘(Solid StateDisk, SSD),它能提供相对于传统旋转磁盘的一种更快速、更强健和更低能耗的选择。
-
磁盘存储
磁盘是由一个或多个叠放在一起的盘片组成的,它们被封装在一个密封的包装里。整个装置通常被称为磁盘驱动器(disk drive),我们通常简称为磁盘(disk)。
-
磁盘存储器(维护着逻辑块号和实际(物理)磁盘扇区之间的映射关系)
当操作系统想要执行一个I/0操作时,例如读一个磁盘扇区的数据到主存,操作系统会发送一个命令到磁盘控制器,让它读某个逻辑块号。控制器上的固件执行一个快速表查找,将一个逻辑块号翻译成一个(盘面,磁道,扇区)的三元组,这个三元组唯一地标识了对应的物理扇区。控制器上的硬件会解释这个三元组,将读/写头移动到适当的柱面,等待扇区移动到读/写头下,将读/写头感知到的位放到控制器上的一个小缓冲区中,然后将它们复制到主存中。
-
磁盘以扇区大小的快来读写数据
-
-
固态硬盘
一个SSD封装由一个或多个闪存芯片和闪存翻译层组成,闪存芯片替代传统旋转磁盘中的机械驱动器,而闪存翻译层是一个硬件/固件设备,扮演与磁盘控制器相同的角色,将对逻辑块的请求翻译成对底层物理设备的访问。
-
存储器层次结构

存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。因此,寄存器文件就是L1的高速缓存,L1是L2的高速缓存, L2是L3的高速缓存,L3是主存的高速缓存,而主存又是磁盘的高速缓存。在某些具有分布式文件系统的网络系统中,本地磁盘就是存储在其他系统中磁盘上的数据的高速缓存。
怎么理解存储层次结构?
存储器层次结构是可行的,这是因为与下一个更低层次的存储设备相比来说,一个编写良好的程序倾向于更频繁地访问某一个层次上的存储设备。所以,下一层的存储设备可以更慢速一点,也因此可以更大,每个比特位更便宜。整体效果是一个大的存储器池,其成本与层次结构底层最便宜的存储设备相当,但是却以接近于层次结构顶部存储设备的高速率向程序提供数据。
局部性思想
这里就是计算机系统中一个基本而持久的思想:如果你理解了系统是如何将数据在存储器层次结构中上上下下移动的,那么你就可以编写自己的应用程序,使得它们的数据项存储在层次结构中较高的地方,在那里CPU能更快地访问到它们。
存储器层次结构的缓存
存储器层次结构的中心思想是,对于每个k,位于k层的更快更小的存储设备作为位于k+1层的更大更慢的存储设备的缓存。
-
缓存数据块概念
第k+1层的存储器被划分成连续的数据对象组块(chunk),称为块(block)。每个块都有一个唯一的地址或名字,使之区别于其他的块。块可以是固定大小的(通常是这样的),也可以是可变大小的(例如存储在Web服务器上的远程HTML文件)。
![image-20220618222123632]()
-
不同层次对之间可以有不同的块大小
-
越低层的设备访问时间越长,所以为了补偿这些较长的访问时间,倾向于使用较大的块
例如,在图6-21中,L1和LO之间的传送通常使用的是1个字大小的块。L2和L1之间(以及L3和L2之间、L4和L3之间)的传送通常使用的是几十个字节的块。而L5和L4之间的传送用的是大小为几百或几千字节的块。一般而言,层次结构中较低层(离CPU较远)的设备的访问时间较长,因此为了补偿这些较长的访问时间,倾向于使用较大的块
缓存访问情况
-
缓存命中
当程序需要第k+1层的某个数据对象d时,它首先在当前存储在第k层的一个块中查找d。如果d刚好缓存在第k层中,那么就是我们所说的缓存命中(cache hit)。
-
缓存不命中
覆盖一个现存的块的过程称为替换或驱逐这个块。被驱逐的这个块有时也称为牺牲块(victim block)。决定该替换哪个块是由缓存的替换策略决定的。常见种类如下:
- 冷命中,缓存为空。
- 冲突不命中,缓存足够大,但因为固定放置测量。
- 容量不命中,因为缓存太小。
缓存管理
-
管理缓存的逻辑可以是硬件,软件,或者是两者的结合
在每一层上,某种形式的逻辑必须管理缓存。这里,我们的意思是指某个东西要将缓存划分成块,在不同的层之间传送块,判定是命中还是不命中,并处理它们。管理缓存的逻辑可以是硬件、软件,或是两者的结合。
-
各层次的管理逻辑
- 编译器管理寄存器文件,缓存层次结构的最高层。它决定当发生不命中时何时加载,以及确定哪个寄存器来存放数据。
- L1、L2和L3层的缓存完全是由内置在缓存中的硬件逻辑来管理的。
- 在一个有虚拟内存的系统中,DRAM主存作为存储在磁盘上的数据块的缓存,是由操作系统软件和CPU上的地址翻译硬件共同管理的。
- 对于一个具有像AFS这样的分布式文件系统的机器来说,本地磁盘作为缓存,它是由运行在本地机器上的AFS客户端进程管理的。
- 在大多数时候,缓存都是自动运行的,不需要程序采取特殊的或显式的行动。
缓存区无处不在

计算机软件-应用程序
程序编译过程
以c语言为例子,在这里,GCC编译器驱动程序读取源程序文件hello.c,并把它翻译成一个可执行目标文件hello。这个翻译过程可分为四个阶段完成,如图所示。

预处理
预处理用于将所有的#include头文件以及宏定义替换成其真正的内容。预处理之后得到的仍然是文本文件,但文件体积会大很多。
编译
将经过预处理之后的程序文本文件编译成特定汇编文件(与即将部署运行的硬件平台使用的指令集架构有关),将生成程序的汇编代码test.s,这也是文本文件。
汇编
汇编就是把生成的汇编指令逐条翻译成机器可以识别的形式,即机器码,这一步产生的文件叫做目标文件,是二进制格式,生成.o文件。
链接
链接过程将多个目标文以及所需的库文件(.so等)链接成最终的可执行文件(executable file)。
加载可执行目标文件

每个Linux程序都有一个运行时内存映像,类似于图7-15中所示。在Linux x86-64系统中,代码段总是从地址0x400000处开始,后面是数据段。运行时堆在数据段之后,通过调用malloc库往上增长。堆后面的区域是为共享模块保留的。用户栈总是从最大的合法用户地址(248-1)开始,向较小内存地址增长。栈上的区域,从地址248开始,是为内核(kernel)中的代码和数据保留的,所谓内核就是操作系统驻留在内存的部分。
计算机软件-操作系统
为什么要操作系统?
可以这么说,操作系统是为应用程序服务的,操作系统通过管理硬件抽象接口,向应用程序提供简单一致和安全的机制来控制各不相同的硬件设备,这样的话,无论是在什么硬件设备,只要设备上运行的操作系统接口是一致的,则应用程序代码无需很大的更改,增强了应用程序的移植性和兼容性。
操作系统怎么实现?
操作系统通过基本的抽象概念(进程、虚拟内存和文件)来实现这两个功能。

进程(多运行程序管理)
进程是操作系统对一个正在运行的程序的一种抽象,给该程序是系统内存中唯一的处理对象的假象。那么一个CPU看上去都像是在并发地执行多个程序,这是通过处理器在进程间切换来实现的,而无需用户来管理。
虚拟内存(多运行程序的内存管理)
虚拟内存是对进程对应程序的存储器的抽象,提供了一个假象,即每个进程都在独占地使用主存。每个进程看到的内存都是一致的,称为虚拟地址空间。这样用户无需考虑实际的物理内存管理,交给操作系统来管理。
文件(程序与IO设备的交互管理)
文件这个简单而精致的概念是非常强大的,因为它向应用程序提供了一个统一的视图,来看待系统中可能含有的所有各式各样的I/O设备。应用程序与io设备的通信交互,可以把其看作是与文件的交互,对于复杂的io设备如磁盘,还有文件系统来管理。
应用程序具体的硬件管理工作交给操作系统来完成,那么用户如何使用进程,文件等这些抽象功能?
通过系统调用,它是用户程序与操作系统之间的接口,这些接口为应用程序提供了简单一致,安全的功能。
操作系统的工作
内核具有很高的权限,可以控制 cpu、内存、硬盘等硬件,而应用程序具有的权限很小,因此大多数操作系统,把内存分成了两个区域:
- 内核空间,这个内存空间只有内核程序可以访问;
- 用户空间,这个内存空间专门给应用程序使用;
用户空间的代码只能访问一个局部的内存空间,而内核空间的代码可以访问所有内存空间。因此,当程序使用用户空间时,我们常说该程序在用户态执行,而当程序使内核空间时,程序则在内核态执行。
应用程序如果需要进入内核空间,就需要通过系统调用,下面来看看系统调用的过程:

内核程序执行在内核态,用户程序执行在用户态。当应用程序使用系统调用时,会产生一个中断。发生中断后, CPU 会中断当前在执行的用户程序,转而跳转到中断处理程序,也就是开始执行内核程序。内核处理完后,主动触发中断,把 CPU 执行权限交回给用户程序,回到用户态继续工作。(这里的中断属于软中断,由操作系统产生,与io设备产生的硬中断是有区别的)





浙公网安备 33010602011771号