Computer Systems:A Programmer's Perspective(CS:APP)

深入理解计算机系统(第一章)

Posted by LT on July 9, 2020

前言

  1. 本书来源于一门课:2015-15-213的ICS(Introduction to Computer Systems)。
    • 在CMU(卡内基梅隆大学)它是一个导论性的课程,作为其它CS/EE专业课的基础,不知道为什么被翻译为“深入理解计算机系统”了。(确实很圣经,深入浅出)
  2. 本书从程序员的角度出发,旨在让应用程序员利用系统知识,写出更好的程序。例如:
    • 在第5章,我们学习如何转换C代码,有利于编译更好工作,调整程序性能。
    • 学习存储器系统(第6章),我们将会知道C编译器是如何把数组放在内存里的。一个直观的例子👇
      • 由于内存里按行访问比按列访问要高效很多,所以,对于二维数组复制,两层循环交换位置,会引起很大的速度差异。
  3. 第3章讲处理器的指令集架构,而第4章讲处理器的微体系结构。

第一章 计算机系统漫游

  1. 像只由ASCⅡ字符构成的文件,称为文本文件(比如.c)。其它所有的文件,都称为二进制文件。
  2. 数字的机器表示,与实际的整数/实数是不同的。比如,浮点数就是对真值的近似编码。
  3. 运行hello程序时发生了什么:
    • 输入./hello,shell程序将字符逐一读入寄存器,再放进内存里。
    • 回车键结束输入,shell将可执行目标文件(hello.o)里的代码和数据从磁盘复制(加载)到内存
    • 运行程序时,指令(hello程序对应的机器指令)从内存复制到处理器
    • 如果程序里有需要print的字符串,字符串复制流向是:内存👉寄存器👉显示设备
  4. 操作系统内核是应用程序和硬件之间的媒介。两个基本功能是:
    • 防止硬件被失控的应用程序滥用
    • 向应用程序提供一致的机制,来控制复杂且各不相同的低级硬件设备。
  5. 为了完成这两个功能,OS提供三个基本抽象
    • 文件是对I/O设备的抽象;
    • 虚拟内存是对主存和磁盘的抽象;
    • 进程是处理器、主存和I/O设备的抽象(一个正在执行的程序的抽象).
    • OS提供的抽象表示
  6. 进程(第8章)是OS对一个正在执行的程序的抽象。
    • 并发:CPU做进程切换,一个进程和另一个进程的指令交错执行
    • 实现交错执行机制称为上下文切换
      • 即,OS内核负责管理当前进程到新进程的转移,保存当前进程上下文,恢复新进程上下文。
      • 内核是OS代码常驻主存的部分,不是独立进程,而是OS管理全部进程所用代码+数据结构的集合。
      • shell进程转hello进程(或者I/O进程),OS执行系统调用,将控制权传给内核。
    • OS跟踪上下文(进程运行时所需的状态信息,比如PC、寄存器当前值,主存内容)。
    • 任何时刻,单处理器只能执行一个进程的代码。
  7. 线程
    • 一个进程由多个线程执行单元组成,共享同样的代码+全局数据。
    • 由于(1)网络服务器有并行处理需求(2)多线程比多进程更容易共享数据(3)线程比进程更高效。
    • 具体地,移步👉线程/并发(12章)
  8. 虚拟内存(第9章)
    • 基本思想:把一个进程的虚拟内存内容存储在磁盘上,用主存作为磁盘的高速缓存。
    • 虚拟内存提供了一种假象:每个进程看到的内存是一样的(虚拟地址空间),好像是独占主存
    • Linux里的虚拟地址空间(下→上:增大)里:
      • 最上面是内核部分(对所有进程都是一样),
      • 最下面是用户进程定义的代码+数据。
    • 虚拟地址空间由大量准确定义的区构成,从下到上,依次是:
      • 代码+数据区(比如C全局变量),在进程开始时就被指定了大小。
      • (运行时)堆,运行时由malloc创建,可动态扩展和收缩。
      • 共享库,比如C标准库/数学库。具体移步👉第7章‘动态链接’。
      • 用户栈,运行时创建,编译器用它来实现函数调用(第3章)。
      • 内核虚拟内存。应用程序要先调用内核,来读写这个区域或者调用内核代码。禁止应用程序直接操作。
  9. 系统之间利用网络通信
    • 网络可视为I/O设备
    • 当系统从主存复制一串字节到网络适配器时,数据流经过网络到达另一台机器。
    • 相似地,系统可以读取从其他机器发送来的数据,并把数据复制到自己的主存。
    • 更多:(11章)将很多前面章节的概念联系在一起,比如实现一个简单的web服务器。
  10. 并发和并行
    • 传统意义上,并发执行只是模拟出来的,就像一个杂耍艺人保持多个球在空中飞舞。
      • 比如,计算机通过在正在执行的进程间快速切换,多线程切换。
      • 对于单核(一个CPU)处理器,基于进程/线程的并发,不是真正意义上的同时
    • 基于线程的并发:
      • 进程并发一样,线程由内核自动调度,并且内核通过一个整数ID来识别线程。
      • I/O多路复用流一样,多个线程运行在单一进程的上下文中,
        • 因此共享一个进程虚拟地址空间的所有内容,包括代码、数据、堆、共享库和打开的文件。
    • 指令级并行(确实有同时的部分)
      • 在流水线中,执行一条指令所需要的活动被划分成不同的步骤,
      • 将处理器的硬件组织成一系列的阶段,每个阶段执行一个步骤。
      • 这些阶段可以并行地操作,用来处理不同指令的不同部分。
      • 在第4章中,我们会研究流水线(pipelining)的使用。
    • 单指令、多数据并行(即SIMD并行)
      • 最低层次上,现代处理器拥有特殊硬件,允许一条指令产生多个可并行执行的操作。
      • SIMD指令多是为了提高处理影像、声音和视频数据应用的执行速度。
      • 对于程序员,可以用编译器支持的特殊的向量数据类型来写程序,比如GCC就支持向量数据类型。
      • 详见第5章-旁注OPT: SIMD中描述了这种编程方式。
    • 第12章会更深人地探讨并发。