回顾:
- 我们编写的代码大量使用了操作系统功能
- 操作系统提供抽象(例如,它隐藏硬件细节)和管理资源
- 必须在多程序编制环境中仔细管理资源
本章小结:
- 从操作系统的角度来看硬件
- 地址空间(Address spaces)
计算机硬件

CPU设计
指令评估
CPU每次执行一个指令序列
CPU的基本周期包括读取、解码和执行(在管道中运行)
超标量(superscalar)CPU提供指令级并行性,并行计算多个指令

高级指令评估
寻找更高的速度:
- 乱序执行(Out-of-order execution) - 指令可能不会按照它们在代码中出现的顺序进行求值
- 投机评估(Speculative evaluation) - 投机评估指令
- ...
您必须非常小心您对CPU行为所做的假设!(编译器优化和内存架构使情况进一步复杂化)
寄存器
寄存器是靠近CPU的小而快速的内存元件
寄存器有多种用途:
- 程序计数器(program counter, PC) - 下一条运行哪条指令
- 程序状态字(program status word, PSW) - 配置CPU状态的标志
- 通用寄存器(general purpose registers) - 存储CPU指令的操作数
编译器/编程器决定在寄存器中保存什么
寄存器是运行程序状态的一部分
多核多线程
摩尔定律: "集成电路(芯片)上的晶体管数量大约每两年翻一番"
密切相关,但不一定与性能相关
摩尔定律仍在继续,但“功率墙(power wall)”减缓了单核/单处理器系统的性能改进
- 为多个“程序”设置几个核心是很容易证明的
- 如何使用大规模并行计算机/ cpu /多核心机器?
大规模并行(massively parallel)
指使用大量独立处理器同时工作以增加计算能力和速度的计算机系统。
现代cpu包含多个核心,并且通常在一个核心中支持多个硬件线程
硬件的发展对操作系统的设计也有影响
- 旧的操作系统如Windows XP不支持多处理器架构
- 现代操作系统以及编译器等其他基础设施需要很好地利用硬件并发性,以充分利用硬件的进步
内存管理单元
如果我们多次运行这段代码,&iVar会显示相同还是不同的地址?
如果我们同时运行两个副本,&iVar会显示相同还是不同的地址?
答:两个进程显示0x10eac2000,相同的地址。每次运行程序时,iVar的值是不同的。
由于地址空间布局随机化(Address Space Layout Randomization, ASLR),Mac上有不同行为。
人们无法知道可执行文件将在内存中的哪个位置运行:
- 可能会受到机器上运行的其他代码的影响
- 同一个程序的多个实例需要不同的内存部分
在编码时:变量有与其相关联的内存——它们需要有一个地址
- 但是在编译时无法知道确切的实际地址(物理地址)
- 编译器只是假设程序将从地址0开始
- 如果程序不是在实际地址0上运行,而是在1000上运行,只需将偏移量(1000)添加到每个“编译地址”上。
有两种不同的地址空间:
- 由程序看到并由编译器使用的逻辑地址空间(logical address space)
- 由硬件/操作系统看到的物理地址空间(physical address space)
编译代码时,内存地址必须分配给变量和指令,编译器不知道物理内存中有哪些内存地址可用
它只是假设代码在生成机器码时从地址0开始运行
在一些罕见的情况下,程序可能在物理地址0运行:physical address = logical address + 0
在其他情况下,它将在物理内存中完全不同的位置运行,并添加偏移量:physical address = logical address + offset
内存管理单元(memory management unit,MMU)负责地址转换(“添加偏移量”):
- 不同的程序实例需要不同的地址转换
- MMU的状态是正在运行的程序状态的一部分
在我们的例子中:
- 打印在屏幕上的地址是逻辑地址
- 逻辑地址通过不同的偏移量转换为两个不同的物理地址
- 代码 printf("Addr:%p; Val:%d\n", &iVar, iVar); 正在打印iVar的逻辑地址。
我们的讨论忽略了许多细节,地址转换可能比统一应用单个偏移量更复杂。更多细节将在稍后的内存管理讲座中介绍。
关键的一点是MMU转换地址所需的数据是正在运行的程序状态的一部分。
- 操作系统设计与硬件设计和功能密切相关
- MMU用于地址转换所需的寄存器内容和数据是正在运行的程序状态的一部分
- MMU抽象了实际内存硬件的细节