CSAPP-01.A tour of computer system

CSAPP 第一章

1.1 信息就是位+上下文

  • 位(bit)由值0和1组成,一个字节有8位。
  • 一个字长,对32位机器是4个字节,对64位机器是8个字节。

1.2 程序被翻译成其他不同的格式

从源程序到可执行目标文件的过程分为4个阶段:

执行这4个阶段的程序(预处理器、编译器、汇编器和链接器)一起构成了编译系统。

hello.c(源程序,文本文件) --> hello.i(添加了头文件的源程序,文本) --> hello.s(汇编程序,文本) --> hello.0(目标程序,二进制)--> hello(可执行的目标程序,二进制)

1.3 为什么要了解编译系统是如何工作的

  1. 优化程序性能

为了在C程序中做出好的编码选择,需要去了解一起机器代码以及编译器将不同的C语句转化为机器代码的方式。

例如:

  • 一个函数调用的开销有多大?
  • while循环比for循环更有效吗?
  • 指针引用比数组引用更有效吗?

第3章会介绍编译器如何把不同的C语言结构转换成他们的机器语言的。第5章会学习简单的转换C语言代码。

  1. 理解链接时出现的错误
  • 链接器报告无法解析一个引用,这是什么意思?
  • 静态变量和全局变量的区别是什么?
  • 不同的C文件中定义了两个相同的全局变量会发生什么?
  • 为什么有些链接错误直到运行时才会出现?

第7章会解释这些。

  1. 避免安全漏洞

缓冲区溢出错误。第3章会描述堆栈原理和缓冲区溢出错误。

1.4 处理器读并解释存储在存储器中的指令

1.4.1 系统硬件的组成

  • 总线: 每次传送1个字。

  • I/O 设备: I/O总线和I/O设备之间传递信息。

  • 主存: 一组动态随机存取存储器(DRAM)芯片组成。存储器是一个线性字节数组,每个字节都有其唯一的地址(即数组索引)。

  • 处理器: 中央处理单元(CPU),解释(或执行)在主存中指令的引擎。处理器核心是一个字长的存储设备(或寄存器),称为程序计数器(PC)。在任何时刻,PC都指向主存中某条机器语言指令(即含有该条指令的地址)。

处理器是按照一个简单的指令执行模型来操作的,这个模型是由指令集结构决定的。PC读取指令,解释指令中的位,执行该指令的简单操作,然后更新PC,使其指向下一个指令,而这条指令并不一定与存储器中刚刚执行的指令相邻。

这样的操作是围绕主存、寄存器文件(register file)、算术逻辑单元(ALU)进行的。

CPU指令可能会要求如下操作:

  • 加载:一个字节或一个字,从主存到寄存器
  • 存储:一个字节或一个字,从寄存器到主存
  • 操作:两个寄存器的内容复制到ALU,进行算术操作
  • 跳转:从指令本身中抽取一个字,复制到PC中。

1.4.2 运行hello程序

图中黑色的线就是整个流程。shell外壳程序将字符读入寄存器,再存放到存储器中。一旦代码和数据加载到主存中,处理器就开始执行hello程序中的main程序中的机器语言指令。

利用存储器存取的技术,数据可以不通过处理器直接从磁盘到达主存。如下图:

然后从主存复制到寄存器文件中,再从寄存器复制到显示设备上。过程如下图:

  • 机器指令最初是放在磁盘上的,
  • 然后加载程序,复制到主存
  • 处理器运行程序时,指令从主存到处理器

同样的,“hello word” 初始是在磁盘上的,然后复制到主存,最后从主存复制到显示器。

1.5 高速缓存至关重要

可以发现这些复制减缓了程序的速度。

而读取速度: 存储器 >> 寄存器(存放几百字节) >> 主存(存放几十亿字节) >> 磁盘(可能比主存大1000倍,比如2T的硬盘,2G的内存.)

因此有了高速缓存存储器。

L1、L2高速缓存用一种静态随机访问存储器(SRAM)的硬件技术实现的。让高速缓存存放可能经常访问的数据时,可以大大提高程序的性能。

1.6 存储设备形成层次结构

存储器层次存储的主要思想是,速度更快的一层作为下一层的缓存区。

1.7 操作系统管理硬件

操作系统可以看做应用程序和硬件之间的一层软件。

1.7.1 进程

一个CPU看上去像是在并发的执行多个进程,这是通过处理器在进程间切换实现的。操作系统实现这种交错执行的机制称为上下文切换。第8章会详细介绍。

1.7.2 线程

一个进程实际上可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。多线程比多进程更容易共享数据,线程一般来说比进程更高效。

1.7.3 虚拟内存

  • 程序代码和数据
  • 堆:在运行时动态扩展和收缩。
  • 共享库
  • 栈:用户栈,编译器用它来实现函数调用。
  • 内核虚拟内存:为内核保留的。

1.7.4 文件

文件就是字节序列。每个I/O设备都可以看成是文件。系统的所有输入输出都是通过使用一小组称为Unix I/O的系统函数调用读写文件实现的。第10章会学习Unix I/O

1.8 系统之间利用网络通信

网络也是一种I/O设备。

这种客户端与服务器之间交互的类型在所有网络应用中是非常典型的。在第11章中,你将会学会如何构造网络应用程序,并创建一个简单的Web服务器。Exciting!

1.9 重要主题

1.9.1 Amdahl定律

系统运行时间 \(T_{old}\), 系统某部分执行时间占比 \(\alpha(0<\alpha <1)\), 该部分提升性能比例 \(k(k>1)\),则总的执行时间: \[T_{new}=(1-\alpha)T_{old}+(\alpha T_{old})/k = T_{old}[(1-\alpha)+\alpha/k]\]

\[S=T_{old}/T_{new} = \dfrac{1}{(1-\alpha)+\alpha/k}<k\]

简单的数学运算,证明只提升系统某一部分的性能,对整体的加速明显小于这一部分提升的比例。也就是说,要加速整个系统,必须加速这个系统中的大部分的速度。

练习题 1.1

T_{old}=25

T_{new}=1500/150+(2500-1500)/100=20

加速比: T_{old}/T_{new}=1.25

1.9.2 并发(concurrency)和并行(parallelism)

  1. 线程级并发

多核处理器:

超线程,有时又称为同时多线程(simultaneous multi-threading),是一项允许一个CPU执行多个控制流的技术。第12章会更深入的讨论并发。

  1. 指令集并行

最近的处理器可以保持每个始终2~4条指令的执行效率。其实每条指令从开始到结束需要长得多的时间,大约20个或更多个周期。在第4章,会研究流水线(pipelining)的使用。在流水线中,将执行一条指令所需要的活动划分成不同的步骤,将处理器的硬件组织成一些列的阶段,每个阶段执行一个步骤。

处理器达到比一个周期一条指令更快的执行速率,就称之为超标量(super-scalar)处理器。

  1. 单指令、多数据并行

一条指令产生多个可以并行执行的操作,这种方式称为单指令、多数据,即 SIMD 并行。

1.9.3 计算机系统中抽象的重要性

文件是对 I/O 设备的抽象,虚拟内存是对程序存储器的抽象,而进程是对一个正在运行的程序的抽象。 虚拟机是对整个计算机的抽象。

1.10 小结