CSAPP 01 - 初探
计算机系统是由硬件和软件组成的,他们共同工作来运行应用程序。
信息的表示
系统中所有的信息:磁盘文件,内存中的程序,网络上传输的用户数据。都是由一串比特
表示的。区分不同数据对象的唯一方法是读取对象时的上下文。
hello.c 程序由一系列值为 0 和 1 的位
组成,8 个位组成一组,又称为字节
。其中每个字节分别代表源程序中的某个字符。
大部分计算机系统都使用ASCII
标准来表示字符:即用唯一的单字节整数值来代表某个字符。像 hello.c 这样只由 ASCII 字符组成的文件叫文本文件
,其他的文件都称为二进制文件
。
翻译程序
hello 程序生命周期是从一个高级语言 C 语言开始的。人类能读懂 hello.c,但是机器却无法理解。要在系统上运行该程序,必须将每条 C 语句都转化成一系列低级机器语言
指令,然后这些指令按照可执行目标程序
的格式打包,并以二进制磁盘文件的形式保存起来。
从源文件到目标文件的转化是由编译器驱动程序
完成的:
hello.c (text) -> 预处理器 (cpp) -> hello.i (text)
hello.i (text) -> 编译器 (cc1) -> hello.s (text)
hello.s (text) -> 汇编器 (as) -> hello.o (binary)
(hello.o + printf.o) (binary) -> 连接器 (ld) -> hello (exe) (binary)
- 预处理阶段:cpp 程序根据以 # 开头的命令 (预处理指令),修改原始 C 程序,得到另一个 C 程序 x.i。
- 编译阶段:cc1 程序将上一步得到的 x.i 程序翻译成一个
汇编语言程序
x.s。
汇编语言是一种低级的机器语言,它为不同高级语言的不同编译器提供了通用的输出语言。
- 汇编阶段:as 程序将上一步得到的 x.s 程序翻译成机器语言指令,并把这些指令打包成
可重定位目标程序
的格式,保存到一个二进制文件 x.o。 - 链接阶段:由于 hello 程序使用了 printf 函数,该函数保存在一个
预编译
的 printf.o 二进制文件中,连接器将这两个二进制文件合并到一起,得到 hello 可执行文件。
系统的硬件组成
一个典型系统的硬件组成如下:
- 总线:总线是一组电子管道,携带信息字节并负责在各个部件间传递。总线通常被设计成传送定长的字节块,称为字,字长取决于系统参数,一般是 8 (64 位系统)。
- I/O 设备:I/O 设备是系统与外界交互的联系通道,包括键盘鼠标等。每个 I/O 设备都通过一个控制器或适配器与 I/O 总线相连。
控制器与适配器的区别在于封装方式,控制器是 I/O 设备本身或系统主板上的芯片组,适配器是一块插在主板插槽上的卡。他们的功能都是在 I/O 总线和 I/O 设备间传递信息。
- 主存:主存是一个临时储存设备,由一组
动态随机存取存储器
芯片 (DRAM) 组成。在处理器运行程序时,用来存放程序指令和处理的数据。
主存在逻辑上就是一个线性的字节数组,每个字节都有自己唯一的编号 (索引),即内存地址,编号从 0 开始。
- 处理器:CPU 是解释 (执行) 存储在主存中指令的引擎。从系统通电开始,CPU 会一直执行
程序计数器
指向的指令,并更新它的值。
程序计数器 (PC) 是内置在 CPU 中的一个寄存器,它大小一个字长。在任何时刻,PC 寄存器都指向某条机器指令,即存储该指令的地址,注意:这条指令并不一定和刚才执行的指令相邻。
储存层次结构
一个储存器结构层次结构示例:
储存器结构层次的主要思想就是:上一层储存器作为低一层储存器的高速缓存。寄存器作为 L1 的高速缓存,L1 作为 L2 的高速缓存。同时主存作为磁盘的高速缓存,磁盘又可以作为网络中其他系统磁盘的高速缓存。
高速缓存
降低 CPU 执行速度一个主要原因是频繁的从内存中读写数据,CPU 执行运算的速度比读写内存快了好几个数量级。寄存器作为内置在 CPU 中的临时存储器,CPU 对他的读写速度远远超过内存。但是寄存器容量小,造价昂贵。因此出现了高速缓存技术。
高速缓存利用局部性原理
:程序有访问局部区域代码和数据的趋势,来加速程序对数据的读写。将大部分的内存操作放在高速缓存中完成该。现代计算机通常有多层高速缓存,其中 L1 内置在 CPU 中,因此读写 L1 的速度相当于读写寄存器。L2 通过一条特殊的总线连接到 CPU,访问 L2 比 L1 慢不少,但是也比访问内存快得多。
L1 和 L2 通过静态随机访问存储器
(SRAM) 的硬件技术实现,同时较新的处理器可能还有 L3 作为第三层高速缓存。
重要的抽象
计算机系统中的几个伟大的抽象:
- 进程:进程是操作系统对一个正在运行的应用程序的抽象。在一个系统上可以同时运行多个程序,这些程序好像独占的使用处理器,主存,I/O 设备。
一个进程实际上还存在多个称为线程
的执行单元,每个线程都运行在进程的上下文中,共享同样的代码和全局数据。
- 虚拟内存:虚拟内存是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独占的使用主存。每个进程看到的内存结构都是一致的,称为
虚拟地址空间
。
-
文件:文件就是字节序列,仅此而已。每个 I/O 设备都能看作是文件,系统中所有的输入输出都是通过系统函数调用读写文件来实现的。
-
指令集体系架构:ISA 作为处理器硬件的抽象。
-
虚拟机:虚拟机作为操作系统,进程的整体抽象。
并发和并行
并行和并发技术就是让处理器同时能做更多事情,有三个层次可以改进:
- 线程级并发
- 增加处理器的核心数量,通常每个核心都包含自己的 L1 和 L2 高速缓存,所有的核心共享 L3 缓存。
- 超线程技术:让 CPU 可以在单个时钟周期上决定执行哪个线程。
- 指令级并行
- 流水线:通常执行一条指令所需要的活动可以被划分成不同的步骤,可以将 CPU 硬件组织成一些列阶段,并行的执行每个阶段。
- 超标量:让处理器做到比一个时钟周期执行一条指令更快的速率。
- 单指令,多数据并行
- SIMD 并行:允许一条指令产生多个可以并行执行的操作。