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)
  1. 预处理阶段:cpp 程序根据以 # 开头的命令 (预处理指令),修改原始 C 程序,得到另一个 C 程序 x.i。
  2. 编译阶段:cc1 程序将上一步得到的 x.i 程序翻译成一个汇编语言程序 x.s。

  汇编语言是一种低级的机器语言,它为不同高级语言的不同编译器提供了通用的输出语言。

  1. 汇编阶段:as 程序将上一步得到的 x.s 程序翻译成机器语言指令,并把这些指令打包成可重定位目标程序的格式,保存到一个二进制文件 x.o。
  2. 链接阶段:由于 hello 程序使用了 printf 函数,该函数保存在一个预编译的 printf.o 二进制文件中,连接器将这两个二进制文件合并到一起,得到 hello 可执行文件。

系统的硬件组成

  一个典型系统的硬件组成如下:

  1. 总线:总线是一组电子管道,携带信息字节并负责在各个部件间传递。总线通常被设计成传送定长的字节块,称为字,字长取决于系统参数,一般是 8 (64 位系统)。
  2. I/O 设备:I/O 设备是系统与外界交互的联系通道,包括键盘鼠标等。每个 I/O 设备都通过一个控制器或适配器与 I/O 总线相连。

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

  1. 主存:主存是一个临时储存设备,由一组动态随机存取存储器芯片 (DRAM) 组成。在处理器运行程序时,用来存放程序指令和处理的数据。

  主存在逻辑上就是一个线性的字节数组,每个字节都有自己唯一的编号 (索引),即内存地址,编号从 0 开始。

  1. 处理器:CPU 是解释 (执行) 存储在主存中指令的引擎。从系统通电开始,CPU 会一直执行程序计数器指向的指令,并更新它的值。

  程序计数器 (PC) 是内置在 CPU 中的一个寄存器,它大小一个字长。在任何时刻,PC 寄存器都指向某条机器指令,即存储该指令的地址,注意:这条指令并不一定和刚才执行的指令相邻。

储存层次结构

  一个储存器结构层次结构示例:

  储存器结构层次的主要思想就是:上一层储存器作为低一层储存器的高速缓存。寄存器作为 L1 的高速缓存,L1 作为 L2 的高速缓存。同时主存作为磁盘的高速缓存,磁盘又可以作为网络中其他系统磁盘的高速缓存。

高速缓存

  降低 CPU 执行速度一个主要原因是频繁的从内存中读写数据,CPU 执行运算的速度比读写内存快了好几个数量级。寄存器作为内置在 CPU 中的临时存储器,CPU 对他的读写速度远远超过内存。但是寄存器容量小,造价昂贵。因此出现了高速缓存技术。

  高速缓存利用局部性原理程序有访问局部区域代码和数据的趋势,来加速程序对数据的读写。将大部分的内存操作放在高速缓存中完成该。现代计算机通常有多层高速缓存,其中 L1 内置在 CPU 中,因此读写 L1 的速度相当于读写寄存器。L2 通过一条特殊的总线连接到 CPU,访问 L2 比 L1 慢不少,但是也比访问内存快得多。

  L1 和 L2 通过静态随机访问存储器 (SRAM) 的硬件技术实现,同时较新的处理器可能还有 L3 作为第三层高速缓存。

重要的抽象

  计算机系统中的几个伟大的抽象:

  1. 进程:进程是操作系统对一个正在运行的应用程序的抽象。在一个系统上可以同时运行多个程序,这些程序好像独占的使用处理器,主存,I/O 设备。

  一个进程实际上还存在多个称为线程的执行单元,每个线程都运行在进程的上下文中,共享同样的代码和全局数据。

  1. 虚拟内存:虚拟内存是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独占的使用主存。每个进程看到的内存结构都是一致的,称为虚拟地址空间

  1. 文件:文件就是字节序列,仅此而已。每个 I/O 设备都能看作是文件,系统中所有的输入输出都是通过系统函数调用读写文件来实现的。

  2. 指令集体系架构:ISA 作为处理器硬件的抽象。

  3. 虚拟机:虚拟机作为操作系统,进程的整体抽象。

并发和并行

  并行和并发技术就是让处理器同时能做更多事情,有三个层次可以改进:

  1. 线程级并发
  • 增加处理器的核心数量,通常每个核心都包含自己的 L1 和 L2 高速缓存,所有的核心共享 L3 缓存。
  • 超线程技术:让 CPU 可以在单个时钟周期上决定执行哪个线程。
  1. 指令级并行
  • 流水线:通常执行一条指令所需要的活动可以被划分成不同的步骤,可以将 CPU 硬件组织成一些列阶段,并行的执行每个阶段。
  • 超标量:让处理器做到比一个时钟周期执行一条指令更快的速率。
  1. 单指令,多数据并行
  • SIMD 并行:允许一条指令产生多个可以并行执行的操作。