作者:qwen3.8-max。
一、本章总览
1. 计算机系统的基本组成
- 计算机系统由硬件和系统软件组成。
- 二者共同协作,用于运行应用程序。
- 虽然具体实现不断变化,但系统的基本概念相对稳定。
- 不同计算机系统通常具有相似的硬件和软件组件,并执行相似的功能。
2. 学习本章的目的
理解计算机系统有助于程序员:
- 写出更快速、更可靠、更安全的程序;
- 理解程序在系统中如何被创建、翻译、加载和执行;
- 理解程序性能受哪些因素影响;
- 避免常见系统级编程错误,例如链接错误、缓冲区溢出、数字表示错误等。
二、hello 程序的生命周期
本章以经典 C 程序hello.c为例,追踪一个程序从创建到运行结束的全过程。
#include<stdio.h>intmain(){printf("hello, world\n");return0;}程序生命周期大致为:
- 程序员编写源程序
hello.c; - 编译系统将源程序翻译成可执行目标文件
hello; - shell 加载并运行可执行文件;
- 程序将字符串输出到屏幕;
- 程序终止。
三、1.1 信息就是位 + 上下文
1. 源程序的本质
hello.c是程序员通过编辑器创建并保存的文本文件。- 源程序本质上是由
0和1组成的位序列。 - 每 8 个位组成一个字节。
- 每个字节表示程序中的某个文本字符。
2. ASCII 编码
- 现代计算机系统通常使用 ASCII 标准表示文本字符。
- 每个字符用一个唯一的单字节整数值表示。
例如:
| 字符 | ASCII 值 |
|---|---|
# | 35 |
i | 105 |
n | 110 |
c | 99 |
| 空格 | 32 |
\n | 10 |
3. 文本文件与二进制文件
- 只由 ASCII 字符构成的文件称为文本文件。
- 其他文件称为二进制文件。
4. 核心思想
系统中所有信息,包括磁盘文件、内存中的程序、内存中的用户数据、网络上传送的数据,都是由一串比特表示的。
区分不同数据对象的唯一方法是:
数据对象被读取时的上下文。
同样的字节序列,在不同上下文中可能表示:
- 整数;
- 浮点数;
- 字符串;
- 机器指令;
- 其他数据对象。
5. 程序员需要理解数字表示的原因
- 计算机中的数字表示与真实整数、实数不同;
- 它们是对真值的有限近似;
- 可能产生意想不到的行为;
- 例如浮点数误差、整数溢出等问题。
四、1.2 程序被其他程序翻译成不同的格式
1. 为什么需要翻译
- 高级 C 语言程序便于人类阅读;
- 但计算机不能直接执行 C 语言源代码;
- 必须将 C 语句转换为低级机器语言指令;
- 最终打包成可执行目标程序。
2. GCC 编译命令
在 Unix 系统上:
gcc-ohello hello.cGCC 编译器驱动程序读取源程序hello.c,并翻译为可执行目标文件hello。
3. 编译系统的四个阶段
hello.c ↓ 预处理器 cpp hello.i ↓ 编译器 cc1 hello.s ↓ 汇编器 as hello.o ↓ 链接器 ld hello四个阶段分别是:
- 预处理;
- 编译;
- 汇编;
- 链接。
4. 四个阶段详解
4.1 预处理阶段
执行者:
预处理器 cpp主要工作:
- 根据以
#开头的命令修改原始 C 程序; - 例如处理
#include <stdio.h>; - 将头文件
stdio.h的内容插入程序文本中; - 输出通常以
.i为扩展名。
示例:
hello.c → hello.i4.2 编译阶段
执行者:
编译器 cc1主要工作:
- 将 C 程序翻译成汇编语言程序;
- 输出文本形式的汇编文件。
示例:
hello.i → hello.s汇编语言的特点:
- 用文本格式描述低级机器语言指令;
- 是不同高级语言编译器之间的通用输出语言;
- 例如 C 和 Fortran 编译器可以产生相同形式的汇编输出。
4.3 汇编阶段
执行者:
汇编器 as主要工作:
- 将汇编语言程序翻译成机器语言指令;
- 打包成可重定位目标程序;
- 输出目标文件。
示例:
hello.s → hello.ohello.o是二进制文件。
4.4 链接阶段
执行者:
链接器 ld主要工作:
- 合并多个目标文件;
- 将程序调用的库函数合并进来;
- 生成最终可执行目标文件。
示例中:
hello.o + printf.o → hello其中:
printf是 C 标准库函数;- 它位于预编译好的目标文件
printf.o中; - 链接器负责将其合并到
hello.o中。
最终生成:
可执行目标文件 hello五、1.3 了解编译系统如何工作是大有益处的
1. 优化程序性能
理解编译系统有助于回答以下问题:
switch是否总是比if-else高效?- 函数调用的开销有多大?
while循环是否比for循环更高效?- 指针引用是否比数组索引更高效?
- 为什么把循环求和结果放在本地变量中更快?
- 为什么重新排列算术表达式中的括号会影响性能?
后续章节涉及:
| 章节 | 内容 |
|---|---|
| 第3章 | x86-64 机器语言,C 如何翻译成机器代码 |
| 第5章 | 通过转换 C 代码优化性能 |
| 第6章 | 存储器层次结构,程序如何利用缓存 |
| 第7章 | 链接、静态库、动态库 |
2. 理解链接时出现的错误
常见链接相关问题:
- 链接器报告无法解析某个引用;
- 静态变量和全局变量的区别;
- 不同 C 文件中定义同名全局变量会发生什么;
- 静态库和动态库的区别;
- 命令行中库的排列顺序有什么影响;
- 为什么有些链接错误直到运行时才出现。
3. 避免安全漏洞
- 缓冲区溢出是许多网络和服务器安全漏洞的主要原因;
- 原因是程序员不理解必须限制来自不受信任源的数据数量和格式;
- 学习汇编语言、程序栈、控制信息存储方式,有助于理解缓冲区溢出;
- 程序员、编译器和操作系统都可以采取措施降低攻击风险。
六、1.4 处理器读并解释储存在内存中的指令
1. shell 的作用
运行hello程序:
./helloshell 是命令行解释器:
- 输出提示符;
- 等待用户输入命令;
- 如果输入不是内置命令,则假定它是一个可执行文件;
- shell 加载并运行该文件;
- 等待程序终止。
七、1.4.1 系统的硬件组成
典型系统的硬件主要包括:
- 总线;
- I/O 设备;
- 主存;
- 处理器。
1. 总线
总线是贯穿整个系统的电子通道。
作用:
- 携带信息字节;
- 在各个部件之间传递数据。
特点:
- 总线通常传送定长的字节块,称为字;
- 字长是基本系统参数;
- 常见字长为 4 字节,即 32 位;
- 或 8 字节,即 64 位。
2. I/O 设备
I/O 设备是系统与外部世界交互的通道。
示例设备:
| 设备 | 功能 |
|---|---|
| 键盘 | 用户输入 |
| 鼠标 | 用户输入 |
| 显示器 | 用户输出 |
| 磁盘驱动器 | 长期存储数据和程序 |
每个 I/O 设备通过控制器或适配器连接到 I/O 总线。
控制器与适配器
- 控制器:位于 I/O 设备本身或主板上的芯片组;
- 适配器:插在主板插槽上的卡;
- 二者功能都是在 I/O 总线和 I/O 设备之间传递信息。
3. 主存
主存是临时存储设备。
作用:
- 存放正在执行的程序;
- 存放程序处理的数据。
物理组成:
- 一组 DRAM 芯片。
逻辑结构:
- 存储器是一个线性的字节数组;
- 每个字节有唯一地址;
- 地址从 0 开始。
数据大小示例,在 Linux x86-64 上:
| C 类型 | 字节数 |
|---|---|
short | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
4. 处理器
CPU,即中央处理单元,是解释和执行指令的引擎。
程序计数器 PC
- PC 是一个字长大小的寄存器;
- 在任何时刻指向主存中的某条机器指令;
- 处理器不断执行 PC 指向的指令;
- 然后更新 PC,使其指向下一条指令。
指令执行模型
处理器看似按照简单模型执行:
- 从 PC 指向的位置读取指令;
- 解释指令中的位;
- 执行指令指定的操作;
- 更新 PC,指向下一条指令。
下一条指令不一定紧邻刚执行的指令。
相关硬件组件
- 寄存器文件:一组字长寄存器;
- ALU:算术/逻辑单元,用于计算数据和地址;
- PC:程序计数器。
基本操作类型
| 操作 | 含义 |
|---|---|
| 加载 | 从主存复制一个字节或字到寄存器 |
| 存储 | 从寄存器复制一个字节或字到主存 |
| 操作 | 将两个寄存器内容送入 ALU 运算,结果存入寄存器 |
| 跳转 | 从指令中取出一个字,覆盖 PC 原来的值 |
指令集架构与微体系结构
| 概念 | 含义 |
|---|---|
| 指令集架构 | 描述每条机器代码指令的效果 |
| 微体系结构 | 描述处理器实际如何实现 |
八、1.4.2 运行 hello 程序
运行hello的大致过程:
1. 输入命令
用户输入:
./helloshell 从键盘读取字符,并保存到内存中。
2. 加载可执行文件
用户按下回车后:
- shell 知道命令输入完成;
- shell 执行指令加载可执行文件
hello; - 将
hello目标文件中的代码和数据从磁盘复制到主存。
数据包括:
"hello, world\n"3. DMA 技术
- 数据可以不经过处理器,直接从磁盘到达主存;
- 这种技术称为直接存储器存取,DMA。
4. 执行程序
可执行文件加载到主存后:
- 处理器执行
main函数中的机器语言指令; - 将字符串从主存复制到寄存器;
- 再从寄存器复制到显示设备;
- 最终显示在屏幕上。
九、1.5 高速缓存至关重要
1. 系统性能瓶颈之一
计算机系统花费大量时间在不同位置之间复制数据。
例如hello程序:
磁盘 → 主存 → 处理器 → 显示设备这些复制操作是开销,会降低程序运行速度。
2. 存储设备速度差异
基本事实:
- 较大的存储设备通常较慢;
- 快速设备通常更贵;
- 磁盘容量可能远大于主存;
- 但磁盘访问速度远慢于主存;
- 寄存器文件访问速度远快于主存;
- 处理器与主存之间的速度差距还在增大。
3. 高速缓存的作用
为缓解处理器和主存之间的速度差距,引入:
高速缓存存储器 cache作用:
- 作为暂时集结区域;
- 存放处理器近期可能需要的信息。
4. 多级高速缓存
典型结构:
| 层级 | 位置 | 特点 |
|---|---|---|
| L1 | 处理器芯片上 | 容量较小,速度接近寄存器文件 |
| L2 | 通过特殊总线连接处理器 | 容量较大,比 L1 慢,但比主存快 |
| L3 | 较新系统中存在 | 更大,但仍然比主存快 |
实现技术:
- L1、L2、L3 通常使用 SRAM;
- 主存通常使用 DRAM。
5. 局部性原理
高速缓存有效的原因是:
程序具有访问局部区域里的数据和代码的趋势。
如果经常访问的数据放在缓存中:
- 大部分内存访问可以在快速缓存中完成;
- 程序性能可能显著提升。
十、1.6 存储设备形成层次结构
1. 存储器层次结构思想
每个计算机系统中的存储设备都组织成层次结构。
从上到下:
- 访问速度越来越慢;
- 容量越来越大;
- 每字节成本越来越低。
2. 典型存储器层次结构
| 层级 | 设备 | 说明 |
|---|---|---|
| L0 | 寄存器 | CPU 寄存器,保存来自高速缓存的字 |
| L1 | L1 高速缓存 | SRAM,保存取自 L2 的缓存行 |
| L2 | L2 高速缓存 | SRAM,保存取自 L3 的缓存行 |
| L3 | L3 高速缓存 | SRAM,保存取自主存的缓存行 |
| L4 | 主存 | DRAM,保存取自本地磁盘的磁盘块 |
| L5 | 本地二级存储 | 本地磁盘,保存远程文件 |
| L6 | 远程二级存储 | 分布式文件系统、Web 服务器等 |
3. 层次结构的核心思想
上一层存储器是下一层存储器的高速缓存。
例如:
寄存器文件 是 L1 的缓存 L1 是 L2 的缓存 L2 是 L3 的缓存 L3 是主存的缓存 主存是磁盘的缓存 本地磁盘可以是远程存储的缓存4. 对程序员的意义
程序员理解存储器层次结构后,可以:
- 优化程序性能;
- 减少昂贵访问;
- 提高局部性;
- 更充分利用缓存。
十一、1.7 操作系统管理硬件
1. 操作系统的角色
应用程序不能直接访问硬件,例如:
- 键盘;
- 显示器;
- 磁盘;
- 主存。
它们必须通过操作系统提供的服务。
操作系统可看作:
应用程序和硬件之间的一层软件。
2. 操作系统的两个基本功能
功能一:保护硬件
防止硬件被失控的应用程序滥用。
功能二:提供统一接口
为应用程序提供简单一致的机制,用于控制复杂硬件设备。
3. 操作系统提供的三个基本抽象
| 抽象 | 抽象对象 |
|---|---|
| 进程 | 处理器、主存、I/O 设备 |
| 虚拟内存 | 主存和磁盘 |
| 文件 | I/O 设备 |
十二、1.7.1 进程
1. 进程的定义
进程是操作系统对一个正在运行的程序的抽象。
现代系统可以同时进行多个进程:
- 每个进程看起来好像独占硬件;
- 多个进程并发运行;
- 指令交错执行。
2. 并发执行
并发运行指:
一个进程的指令和另一个进程的指令交错执行。
实现方式:
- 处理器在进程之间切换;
- 单处理器系统通过时间片模拟并发;
- 多核处理器可以真正并行执行多个进程。
3. 上下文
操作系统需要保存进程运行所需的状态信息。
上下文包括:
- PC 的当前值;
- 寄存器文件的当前值;
- 主存内容;
- 其他状态信息。
4. 上下文切换
当操作系统决定将控制权从当前进程转移到另一个进程时:
- 保存当前进程的上下文;
- 恢复新进程的上下文;
- 将控制权传递给新进程。
新进程会从上次停止的地方继续运行。
5. shell 运行 hello 的进程过程
示例场景:
- 最初只有 shell 进程运行;
- 用户输入命令;
- shell 通过系统调用请求操作系统运行
hello; - 操作系统保存 shell 上下文;
- 创建新的 hello 进程;
- 将控制权交给 hello 进程;
- hello 运行并终止;
- 操作系统恢复 shell 上下文;
- shell 继续等待下一条命令。
6. 内核与系统调用
内核
内核是:
操作系统代码常驻主存的部分。
内核不是独立进程,而是:
- 系统管理全部进程所用代码和数据结构的集合。
系统调用
当应用程序需要操作系统服务时:
- 执行一条特殊的系统调用指令;
- 将控制权传递给内核;
- 内核执行请求的操作;
- 然后返回应用程序。
十三、1.7.2 线程
1. 线程的定义
现代系统中,一个进程可以由多个执行单元组成,这些执行单元称为线程。
每个线程:
- 运行在进程上下文中;
- 共享同样的代码和全局数据。
2. 线程的重要性
线程越来越重要,因为:
- 网络服务器需要并行处理;
- 多线程之间比多进程之间更容易共享数据;
- 线程通常比进程更高效;
- 在多处理器系统中,多线程可提高程序运行速度。
十四、1.7.3 虚拟内存
1. 虚拟内存的定义
虚拟内存是一个抽象概念:
它为每个进程提供假象,好像每个进程都在独占使用主存。
每个进程看到的内存是一致的,称为:
虚拟地址空间2. Linux 进程虚拟地址空间结构
从低地址到高地址大致包括:
- 程序代码和数据;
- 堆;
- 共享库;
- 用户栈;
- 内核虚拟内存。
3. 各区域说明
3.1 程序代码和数据
- 代码从固定地址开始;
- 紧接着是与 C 全局变量对应的数据;
- 该区域由可执行目标文件初始化。
例如:
hello 可执行文件3.2 堆
- 位于代码和数据区之后;
- 可在运行时动态扩展和收缩;
- 由
malloc、free等函数管理。
3.3 共享库
- 大约在地址空间中间;
- 存放共享库代码和数据;
- 例如 C 标准库、数学库;
- 与动态链接有关。
3.4 用户栈
- 位于用户虚拟地址空间顶部;
- 编译器用它实现函数调用;
- 函数调用时栈增长;
- 函数返回时栈收缩。
3.5 内核虚拟内存
- 位于地址空间最上部;
- 保留给操作系统内核;
- 应用程序不能直接读写该区域;
- 应用程序必须通过系统调用访问内核功能。
4. 虚拟内存的基本思想
- 进程的虚拟内存内容可以存储在磁盘上;
- 主存作为磁盘的高速缓存;
- 处理器生成的每个地址可能需要硬件翻译。
十五、1.7.4 文件
1. 文件的定义
文件就是字节序列。
每个 I/O 设备都可以看成文件,包括:
- 磁盘;
- 键盘;
- 显示器;
- 网络。
2. Unix I/O
系统中的所有输入输出都通过一组系统函数调用实现:
Unix I/O3. 文件抽象的意义
优点:
- 为应用程序提供统一视图;
- 屏蔽底层设备差异;
- 程序员不必了解具体设备技术;
- 同一程序可以运行在使用不同设备技术的系统上。
十六、1.8 系统之间利用网络通信
1. 网络作为 I/O 设备
从单独系统的角度看:
网络也可以视为一种 I/O 设备。
系统可以:
- 将字节从主存复制到网络适配器;
- 通过网络发送到另一台机器;
- 也可以接收来自其他机器的数据,并复制到本地主存。
2. 网络应用示例
网络使信息复制成为计算机的重要用途:
- 电子邮件;
- 即时通信;
- 万维网;
- FTP;
- telnet。
3. telnet 远程运行 hello 的过程
步骤:
- 用户在本地键盘输入命令;
- 客户端向远程 telnet 服务器发送字符串;
- 服务器将字符串发送给远程 shell;
- 远程 shell 运行 hello 程序;
- 远程程序输出
"hello world\n"; - telnet 服务器将输出发送回客户端;
- 客户端在本地显示器上打印结果。
4. 客户端/服务器模型
这种交互是网络应用的典型模式:
- 客户端发起请求;
- 服务器提供服务;
- 双方通过网络交换数据。
十七、1.9 重要主题
1. Amdahl 定律
1. 基本思想
当对系统的某个部分进行加速时,整体性能提升取决于:
- 该部分的重要性;
- 该部分被加速的程度。
2. 公式推导
设:
- 原执行时间为
Told; - 某部分执行时间占比为
α; - 该部分加速比为
k。
则新执行时间为:
Tnew = Told [(1 - α) + α / k]系统加速比为:
S = Told / Tnew = 1 / [(1 - α) + α / k]3. 示例
假设:
α = 0.6 k = 3则:
S = 1 / (0.4 + 0.6 / 3) S = 1.67说明:
即使对占比 60% 的部分加速 3 倍,整体加速比也只有 1.67 倍。
4. Amdahl 定律的结论
要想显著加速整个系统,必须提升系统中相当大部分的速度。
5. 特殊情况:某部分加速到时间可忽略
当k → ∞时:
Smax = 1 / (1 - α)如果 60% 的系统被加速到几乎不花时间:
Smax = 1 / 0.4 = 2.5即使某部分被极大优化,整体提升仍受其余部分限制。
6. 练习题思想
练习题 1.1
卡车运输例子:
- 总距离 2500 公里;
- 原速度 100 公里/小时;
- 原时间 25 小时;
- 蒙大拿州 1500 公里速度提高到 150 公里/小时。
关键结论:
- 蒙大拿段加速比例为 1.5;
- 总时间从 25 小时降到 20 小时;
- 整体加速比为:
25 / 20 = 1.25×如果要整体加速比达到1.67×,蒙大拿段速度需要非常高,说明局部优化对整体提升有限。
练习题 1.2
目标:
- 整体性能提升
2×; - 可优化部分占
80%。
求该部分需要提升多少。
由:
2 = 1 / [(1 - 0.8) + 0.8 / k]解得:
k = 2.67十八、1.9.2 并发和并行
1. 基本概念
并发
并发是一个通用概念:
一个系统同时具有多个活动。
并行
并行是:
使用并发使系统运行得更快。
2. 三个并行层次
本章重点强调三个层次:
- 线程级并发;
- 指令级并行;
- 单指令、多数据并行。
十九、线程级并发
1. 进程与线程
在进程抽象之上:
- 可同时运行多个程序;
- 一个进程可以有多个线程;
- 多个控制流可以共享进程资源。
2. 单处理器系统
传统系统中:
- 一个时刻只能执行一个程序;
- 操作系统通过快速切换制造并发假象;
- 称为时间共享。
3. 多处理器系统
多处理器系统由多个处理器组成,并由单一操作系统内核控制。
4. 多核处理器
多核处理器:
- 将多个 CPU 核集成到一个芯片上;
- 每个核有自己的寄存器和缓存;
- 可共享更高层缓存和主存接口。
例如四核处理器:
核0、核1、核2、核3每个核可能有:
- L1 指令缓存;
- L1 数据缓存;
- L2 统一缓存;
- 共享 L3 缓存;
- 共享主存接口。
5. 超线程
超线程也称:
同时多线程特点:
- 一个 CPU 可执行多个控制流;
- 某些硬件有多个备份,如 PC、寄存器文件;
- 某些硬件共享,如浮点运算单元;
- 可以在单个周期内选择执行哪个线程;
- 提高 CPU 资源利用率。
示例:
- Intel Core i7 每个核可执行两个线程;
- 四核系统可并行执行八个线程。
6. 多处理器提高性能的两种方式
- 减少模拟并发的开销;
- 使多线程程序运行得更快。
前提:
程序必须以多线程方式编写,并且线程能够高效并行执行。
二十、指令级并行
1. 指令级并行的含义
现代处理器可以同时执行多条指令。
例如:
- 早期处理器执行一条指令需要 3 到 10 个周期;
- 现代处理器可每个时钟周期执行 2 到 4 条指令。
2. 流水线
流水线技术:
- 将指令执行过程划分为多个阶段;
- 每个阶段执行一部分工作;
- 各阶段并行处理不同指令的不同部分。
例如:
取指 → 译码 → 执行 → 访存 → 写回效果:
- 提高指令吞吐率;
- 可接近每周期一条指令。
3. 超标量处理器
如果处理器能达到比每周期一条指令更快的执行速率,则称为:
超标量处理器特点:
- 支持指令级并行;
- 可同时发射和执行多条指令;
- 现代处理器大多支持超标量操作。
二十一、单指令、多数据并行
1. SIMD 并行
SIMD:
Single Instruction, Multiple Data含义:
一条指令产生多个可以并行执行的操作。
例如:
- 一条指令同时对 8 对单精度浮点数做加法。
2. 应用场景
SIMD 常用于:
- 图像处理;
- 声音处理;
- 视频处理;
- 科学计算;
- 高性能计算。
3. 编程方式
有些编译器可以自动提取 SIMD 并行性,但更可靠的方法是使用:
- 编译器支持的特殊向量数据类型;
- 例如 GCC 支持的向量类型。
二十二、1.9.3 计算机系统中抽象的重要性
1. 抽象的意义
抽象是计算机科学最重要的概念之一。
抽象的作用:
- 隐藏实现复杂性;
- 提供简单接口;
- 使程序员可以安全使用底层机制;
- 使系统可移植、可扩展、可维护。
2. 指令集架构
指令集架构是处理器硬件的抽象。
特点:
- 机器代码程序看起来像一次只执行一条指令;
- 实际硬件可能并行执行多条指令;
- 不同处理器实现可以执行相同机器代码;
- 但性能和开销可能不同。
3. 操作系统抽象
操作系统提供三类抽象:
| 抽象 | 对应对象 |
|---|---|
| 文件 | I/O 设备 |
| 虚拟内存 | 主存和磁盘 |
| 进程 | 处理器、主存、I/O 设备 |
4. 虚拟机
虚拟机提供对整个计算机的抽象,包括:
- 操作系统;
- 处理器;
- 程序。
虚拟机思想的优势:
- 可运行不同操作系统;
- 可运行同一操作系统的不同版本;
- 便于隔离和管理;
- 便于运行不同环境的程序。
二十三、第1章核心概念总表
| 概念 | 核心内容 |
|---|---|
| 位、字节、ASCII | 所有信息本质上是位,上下文决定含义 |
| 编译系统 | C 程序经过预处理、编译、汇编、链接生成可执行文件 |
| 处理器 | 读取并解释内存中的指令 |
| 主存 | 临时存储程序和数据 |
| I/O 设备 | 系统与外部世界交互的通道 |
| 总线 | 各组件之间传递数据的通道 |
| 缓存 | 利用局部性提高访问速度 |
| 存储器层次结构 | 寄存器、缓存、主存、磁盘形成层次 |
| 操作系统 | 管理硬件,为程序提供抽象 |
| 进程 | 正在运行程序的抽象 |
| 虚拟内存 | 每个进程独占内存的假象 |
| 文件 | I/O 设备的抽象 |
| 网络 | 可视为 I/O 设备 |
| Amdahl 定律 | 整体加速受未加速部分限制 |
| 并发与并行 | 多活动系统,可用于提升性能 |
| 抽象 | 隐藏复杂性,是系统设计的核心思想 |
二十四、第1章逻辑主线总结
本章围绕hello程序展开,主要回答四个问题:
1. 程序如何表示?
源代码 → 位序列 → ASCII 文本核心思想:
信息就是位 + 上下文。
2. 程序如何被翻译?
hello.c → hello.i → hello.s → hello.o → hello核心工具:
- 预处理器;
- 编译器;
- 汇编器;
- 链接器。
3. 程序如何运行?
磁盘上的可执行文件 → 主存 → CPU 执行指令 → 输出结果涉及硬件:
- 键盘;
- shell;
- 磁盘;
- 主存;
- CPU;
- 显示器。
4. 系统如何管理程序?
操作系统提供三大抽象:
进程 虚拟内存 文件二十五、适合记忆的重点结论
- 系统中所有信息都是位,上下文决定其含义。
- 程序必须经过编译系统翻译成可执行目标文件。
- 编译系统包括预处理、编译、汇编、链接四个阶段。
- CPU 从内存读取并执行指令。
- 存储器速度差异很大,缓存用于弥补处理器和主存之间的速度差距。
- 存储设备形成层次结构,高层设备是低层设备的缓存。
- 操作系统管理硬件,并提供进程、虚拟内存和文件三个抽象。
- 网络也是一种 I/O 设备。
- Amdahl 定律说明系统整体性能提升受未优化部分限制。
- 抽象是计算机系统中最重要的设计思想之一。