之前在读 xv6-book 的时候,发现自己对一些计算机底层的知识了解的太少,导致看到虚拟内存映射、物理地址这些东西的时候就很头大。在一个群友的推荐下,我决定先来看一下CSAPP的1、2、3、6、7、8、9章(当然,还有一种方案是学习CS61C),于是有了这个系列。

gitbook: https://hansimov.gitbook.io/csapp/

系统的硬件组成

1.总线

总线是贯穿整个系统的一组电子管道。它们携带者信息字节在各个部件之间传递,传送定长的字节块(字)。字中的字节数(字长)是一个基本的系统参数,通常是4个字节(32位)、8个字节(64位)。

2.I/O 设备

示例有作为用户输入的键盘和鼠标,作为用户输出的显示器,用于长期存储数据和程序的磁盘驱动器(磁盘)。每个 I/O 设备都通过一个控制器或者适配器与 I/O 总线相连。

控制器和适配器之间的区别在于它们的封装方式: 控制器是 I/O 设备本身或系统的主板上的芯片组,而适配器则是一块插在主板插槽上的卡。功能都是在 I/O 总线和 I/O 设备之间传递信息。

3.主存

主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。从物理上来说,主存是由一组 动态随机获取存储器(DRAM) 芯片组成;从逻辑上来说,存储器是一个线性的字节数组,每个字节都有其唯一的地址,这些地址是从零开始的。

4.处理器

中央处理单元(CPU)简称为处理器,是解释(或执行)存储在主存中指令的引擎。处理器的核心是一个大小为一个字的存储设备(或寄存器),称为程序计数器(PC)。在任何时刻,PC都指向主存中的某条机器语言指令(该指令的地址)

处理器从通电到系统断电一直在不断从程序计数器指向的内存处读取指令,解释指令中的位,执行该指令指示的简单操作,然后更新 PC,使其指向下一条指令。

这样的操作围绕着主存、寄存器文件(register file)和算数/逻辑单元(ALU)进。寄存器文件是一个小的存储设备,由一些单个字长的寄存器组成,每个寄存器都有唯一的名字。ALU计算新的数据和地址值。

CPU在指令的要求下可能会执行如下操作:

  • 加载: 从主存复制一个字节或者一个字到寄存器,以覆盖寄存器原来的内容;
  • 存储: 从寄存器复制一个字节或者一个字到主存的某个位置,以覆盖这个位置上原来的内容;
  • 操作: 把两个寄存器的内容复制到ALU,ALU对这两个字做算数运算,并将结果存放到一个寄存器中;
  • 跳转: 从指令本身抽取一个字,并将这个字复制到PC中,以覆盖PC中原先的值。

操作系统管理硬件

操作系统有两个基本功能∶

  1. 防止硬件被失控的应用程序滥用;
  2. 向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。

操作系统通过几个基本的抽象概念(进程、虚拟内存和文件)来实现。

文件是对 I/O 设备的抽象表示,虚拟内存是对主存和磁盘 I/O 设备的抽象表示,进程则是对处理器、主存和 I/O 设备的抽象表示。

进程

进程是操作系统对一个正在运行的程序进行的一种抽象。一个CPU在同一时间只能执行一个进程,但是可以并发运行,即一个进程的指令和另一个进程的指令是交错执行,操作系统实现这种交错执行的机制称为上下文切换,而上下文就是操作系统保持跟踪进程运行所需的所有状态信息。

线程

在现代操作系统中,一个进程实际上可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。

虚拟内存

使用 xv6 里的解释

虚拟内存是每个进程都会有自己独立的 page table,每一个进程只能访问出现在自己page table中的物理内存。操作系统会设置page table,使得每一个进程都有不重合的物理内存,这样一个进程就不能访问其他进程的物理内存,因为其他进程的物理内存都不在它的 page table 中。

就比如 ls 程序会有一个内存地址 0,echo 程序也会有一个内存地址 0,但是操作系统会将两个程序的内存地址0映射到不同的物理内存地址,所以ls程序不能访问echo程序的内存,同样echo程序也不能访问ls程序的内存。

文件

文件就是字节序列。每个I/O设备,包括磁盘、键盘、显示器,甚至网络,都可以看成是文件。系统中的所有输入输出都是通过使用一小组称为 Unix I/O 的系统函数调用读写文件来实现的。

系统之间利用网络通信

从一个单独的系统来看,网络可视为一个 I/O 设备,当系统从主存复制一串字节到网络适配器时,数据流经过网络到达另一台机器,相似地,系统可以读取从其他机器发送来的数据,并把数据复制到自己的主存。