Overview
Prelogue
笔者武大计科大二在读。本学期学院开设了计算机系统基础课程,课程基本基于CMU的slides和深入理解计算机系统一书。很幸运上课的教授是中文版译者之一的龚教授。但由于本人基础薄弱,上课很难完全get到教授传递的知识,对那本700多页的黑书更是望而却步,加之期末考试临近,因此我决定认真复习一遍slides,并尝试阅读书上对应的章节和完成一些课后作业,同时利用markdown记录复习时的一些知识点和心得体会。
复习笔记将分为三个板块:
- Slides Review
- Book Reading
- Homework
Slides Review: Course Overview
Some Terms
slides是全英文的,另外以后还打算啃一遍英文原版的CSAPP,故积累一些英文术语是有必要的。
| English | 汉语 |
|---|---|
| asympotic analysis | 渐进分析 |
| asympotic complexity | 渐进复杂度 |
| underlying | 根本的;底层的 |
| implementation | 实现 |
| tune | 调试 |
| embedded systems | 嵌入式系统 |
| conputer architecture | 计算机体系结构 |
| commutativity | 交换性 |
| associativity | 结合性 |
| distributivity | 分配性 |
| monotonicity | 单调性 |
| malware | 恶意软件 |
| critical state | 临界状态 |
| ML (machine language) | 机器语言 |
| autonomous | 自治的 |
| throughput | 吞吐量 |
Great Reality
1. Ints are not Integers, Floats are not Reals
意思是”(计算机中的)整数不是(数学上的)整数,浮点数不是实数“,想传递的意思大概是计算机中的数学不能与我们理论上学的数学完全等同。
即整型会溢出,例子中是上溢出。而浮点数不会有这种情况(下一章就会讲)。
即浮点数的运算可能不满足结合律。
2. You've Got to Know Assembly
我们可能不会用汇编语言写代码,但我们得能读它。
3. Memory Matters
内存访问bug:
typedef struct {
int a[2];
double d;
} struct_t;
double fun(int i) {
volatile struct_t s;
s.d = 3.14;
s.a[i] = 1073741824; /* Possibly out of bounds */
return s.d;
}
注意:不同系统结果不一样!
4. There’s more to performance than asymptotic complexity
在数据结构中,我们着重讨论算法在理论上的渐进复杂度,并认为其是影响算法性能的主要因素。但可以优化的地方不止,比如代码的书写方式就很大程度上影响了某些算法的性能,例如:
这个算法就是实现了二维数组的复制,但左边是行优先,而右边是列优先。很明显,行优先的效率更高。
5. Computers do more than execute programs
Book Reading: A Tour of Computer Systems
1. 信息就是位 + 上下文
源程序(.c文件)
源程序实际上就是一由个值0和1组成的位(又称为比特)序列,8个位被组织成一,组称为字。节每字个节表示程序中的某些文本字符。
大部分现代的计算系统机都使用ASCII标准表示来文本字符,这种方式实际上就是用一个唯一的单字节大小整数的值表示来每字符个。
#include<stdio.h>
int main()
{
print("hello, world\n");
return 0;
}
ASCII码表示:
像
hello.c这样只由ASCII字符构成的文件称为文本文件,所有其他文件都称为二进制文件。
分不数据同对象的唯一方法是们我读到这些数据对象时的上下文。比如,如在不同的上下文中,一同样个字的节序列可能表示一个整数、浮点、数字符串或机者器指令。
补充:
字节和字
| 名称 | 比特数 |
|---|---|
| 字节(byte) | 8 |
| 字(word) | 32位计算机:1字=32位=4字节;64位计算机:1字=64位=8字节 |
2. 程序被翻译成不同格式
目标文件
为了在系统上运行hello.c程序,每条C语句都必须被他其程序转化为一系列低级的机器语言指令。然后这指令些按照一种称为可执行目标程序的格式打好,包并以二进磁盘制文件形式的存放起来。目标程序也称为可执行目标文件。
在Unix系统,上从源文件到目标文件转化的由是编译驱动器程序完成的:
linux> gcc -o hello hello.c
在这里,GCC编译驱动器程序取读源程序文件hello.c,并把它翻译成一可个执行目标文件hello。这个翻译过可程分四为个阶段。
编译系统
预处理器、编译、器汇编和器链接器一起构成了编译系统(compilationsystemy) 。
预处理阶段
预处理器 (cpp) 根据字符以#开头的命令,修原始改的C程序。比如hello.c中第1行的#include<stdio.h>命令告诉预处理器取读系统头文件stdio.h的内容,并把直接它插人程序文本中。结果就得到了另一C个程序,通常是以.i作为文件扩展名。
编译阶段
编译 (ccl) 器将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。该程序包含函数main的定义。
main:
subq $8,%rsp
mov $.LCO,%edi
Call puts
mov1 $0,%eax
addq $8,%rsp
ret
汇编阶段
汇编器 (as) 将hello.s翻译成机器语言指令,把这指令些打包成一种叫做可重定位目标程序 (relocatable object program) 的格式,并将结果保存在目标文件hello.o中。hello.o文件是一个二进制文件,它包含的17个字节是函数main的指令编码。如果我们在文本编辑器中打开hello.o文件,将看到一堆乱码。
链接阶段
he11o程序调用了printf函数,它是每个C编译器提供都的标准C库中的一个函数。printf函数存在于一个名为printf.o的单独的预编译好了的目标文件,中而这个文件必须以某方式种合并到我们的hello.o程序。链接器(ld)就负责处这理种合并。结果就得到hello文件,它是一个可执行目标文件(或简称者为可执行文件),可以被加载到内存中(但一开始是存放在磁盘上),由系统执行。
3. 处理器读并解释储存在内存中的指令
shell
shell是一个命令行解释器,它输出一个提示符,等待输入一个命令行,然后执行这个命令。如果该命令行的第一单词个不是一内个置的shell命令,那么shell就会假设这是一可个执行文件的名字,它将加载并运行这个文件。
若要运行目标文件hello,则在shell中输入:
linux> ./hello
hello, world
linux>
4. 系统的硬件组成
总览
重点看看主存(memory)和处理器(processor)。
主存
主存是一个临时存储设备,在处理器执行程序时用来存放程序和程序处理的数据。
从物理上来说,主存是由一组动态随机取存存储(DRAMD)器芯片组成的。
从逻辑上来说,存储器是一个线性的字节数组,每字个节都有其唯一的地址(数组索引),这些地址是从零开始的。
处理器
中央处理单元(CPU),简称处理器是解释(或执行)存储在主存中指令的引擎。处理器的核心是一个大小为一字个的存储设备(或寄存器),称为程序计数器(PC) 。在任何时刻,PC都指向主中存的某条机器语言指令(即含有该条指令的地)址。
从系统通电开始,直到系统断电,处理器直一在不断地执行程序计数器指向的指令,再更新程序计数器,使指向其下一条指令。
寄存器文件
是一个小存储的设备,由一些单个字长寄存的器组成,每个寄存器都有唯一的名字。
ALU
计算新的数据和地址值。
加载
从主存复制一字个节或者一个字到寄存器以覆盖寄存器原来的内容。 存储
从寄存器复制一字个节或者一个字到主存的某个位置,以覆盖这个位置上原来的内容。 操作
把两寄个存器的内容复制ALU,ALU到对这两字个做算术运算,并将结果存放到一寄存个器,中以覆盖寄存该中器原来内的容。 跳转
从指令本中身抽取一个字,并这将个字复制到程序计数器(PC)中,以覆盖PC中原来的值。
5. 存储设备的层次结构
存储层次器结构主要的思想是上一层存储的作为器低一层存储器的高速缓存。
6. 操作系统管理硬件
我们可以把操作系统看成是应用程序和硬件之间插入的一层软件,所有应用程序对硬件的操作尝试必须都通过操作系统。
操作系统两个基本功能:
- 防止硬件被失控的用应程序滥用;
- 向应用程序提供简单一致的机制控制来复杂而又通常大不相同低级的硬件设备。
操作系统通过进程、虚拟内存和文件来实现这两个功能。
进程
操作系统会提供一种假象,就好像系统上只有这个程序在运行。程序看上去是独占地使用处理器、主和存I/O设备。处理器上看去就像 在间断不地一条接一条地执行程序中的指令,即该程序的代码和数据系统是内存中的唯一对 象。这些假象是通过进程的概念来实现的。 进程
操作系统对一个正在运行的程序的一种抽象。在一个系统上可以同时运行多个 进程,而每个进程都好像独占在地使用硬件。
并发运行
一个进程的指令和另一个进程的指令是交错执行的。在大多数系统中,需要运行进程的数多是于可以运行它们的 CPU个数的。
上下文切换
操作系统实现这种交错执行的机制。
上下文
操作系统保持跟踪进程运行所需的所有状态信息。比如PC和寄存器文件当前的值,以及主存的内容。
在任何一个时刻,单处理器系统只都能执行一个进程的代码。当操作系统决定要把控制从权当前进程转移到某个新进 程时,就会进行上下文切换,即保存当前进程的上下文、恢复新进程的上下文,然后将控制权传递到新进程。新进程就会从它上次停止方地的开始。
线程
在现代系统中,一个进程实际上可以由多个称为线程的执行单元组成,每个线程运行都在进程的上下文中,并共享同样的 代码和全局数据。
虚拟内存
虚拟内存是一抽象个概念,它为每个进程提供了一个假象,即每个进程都独占地在使用主存。每个进程到看的内存都是一致的,称为虚拟地址空间。
7. Amdahl定律
Homework
可知\alpha=0.8,S=2,代入公式得k=2.67。