[What]A Tour of Computer Systems

重新认识计算机系统。

信息是由二进制和语境组成的

在计算机中,所有的信息都是由 0 和 1 这样的很多个二进制位组成的,8位组成一个字节。 至于一个字节或多个字节所表达的意义,则是由其语境而定的。

  • 比如可以表示字符,数字,寄存器命令,地址等很多信息。

语境是由程序员来确定的,而语境到实际对应的二进制则是由编译器来完成的。

编译的流程

编译经过了以下4个步骤:

  • 预编译(Preprocessing):将包含的头文件展开,替换宏定义,取消注释,最终生成 .i 结尾的文件
  • 编译(Compilation):将 .i 文件中的语言,编译为目标机的汇编语言,最终生成 .s 结尾的文件。
    • 不同的语言,不同的编译器,到了这一步都是一样的汇编语言。
  • 汇编(Assembly):将 .s 结尾的文件翻译为机器语言,并将内容打包为可以重定位的 .o 文件。
  • 链接(Linking):将可重定位文件中的外部引用符号与其定义建立地址链接,重新梳理为一个可执行文件。

计算机系统的硬件组成

hd_organization.jpg

总线

在计算机系统中,都是通过总线来连接各个组件的。总线的宽度,也就是一次传输的字节数,就被称为字长。

I/O 设备

I/O设备是与挂载在I/O总线上的控制器或适配器连接的。

  • 控制器(controller) : 一般是指芯片自带的,或者直接焊接在母板上的控制器。
    • 比如集成显卡
  • 适配器(adapter): 一般是指安装母板上的接口槽的设备。
    • 比如独立显卡

存储器

存储器一般由许多DRAM(dynamic random access memory)组成,其每个字节都具有独立地址,可以随机访问。

处理器

处理器通过PC(program counter)寄存器的指定,从内存中读取指令进行处理,然后将PC指向下一个指令地址,如此循环往复。

其流程概览如下:

  1. 载入(Load): 从内存读取一字节或一个字长的指令或数据到内部寄存器
  2. 存储(store):将内部寄存器的一字节或一个字长覆盖到内存原来存储该数据的地址
  3. 执行(Operate): 从内部寄存器取出两个内容到运算逻辑单元ALU(arithmetic/logic unit),ALU将对两个字进行操作,

然后将操作的结果写回到一个寄存器,覆盖原来的存储位置。

  1. 跳转(Jump):将下一条指令的地址赋值给PC寄存器

内部缓存(cache)

CPU要先将硬盘的代码载入内存中执行,而后CPU要通过内部寄存器与内存反复多次的交互。 但由于CPU的速度比内存快大约100倍,而内部寄存器容量太小(大约几百字节),这导致CPU很多时候都在等内存而浪费了很多时间。

为此,计算机学家发明了使用SRAM(static random access memory)做成的内部缓存(Cache),这事典型的空间换时间策略,Cache包括:

  • 一级缓存(L1):其速度与内部寄存器接近,容量大约几万字节
  • 二级缓存(L2):其速度比L1慢5倍左右(但也比内存快5~10倍),容量大约十几万到数百万字节。

部分CPU还具有三级缓存(L3)。

这些存储器缓存以金字塔结构组成:

memory_hierarchy.jpg

操作系统来管理计算机硬件系统

操作系统将I/O设备,内存,处理器以下图的方式进行抽象给应用程序:

os_abstraction.jpg
  • I/O设备被抽象成了文件
  • 内存和I/O设备被抽象成了虚拟内存
    • I/O设备中的块设备数据在内核中都有缓存
  • 处理器、内存和I/O设备被抽象成了进程
    • 进程是资源分配的基本单位,一个进程包含此3个基本资源

进程

每个进程在操作系统的调度下工作,每个进程都被认为独占系统资源, 内核在通过切换进程上下文来达到切换不同进程运行的目的,从宏观上来看它们是并发运行的。

虚拟内存

虚拟内存使得进程以为自己独占整个内存,当应用程序运行时,其内存在Linux中分配如下图:

virtual_address.jpg
  • 在meltdown漏洞出来后,每个进程的内核区映射仅有进行页表切换的代码了,内核有自己单独的页表。

文件

在Linux中所有的I/O操作都通过VFS虚拟为了文件操作,这使得编程简易。

网络使得不同的操作系统可以通信

遵从TCP/IP协议的操作系统都可以相互通信。

重要概念

Amdahl's Law

Gene Amdahl 对于提高系统性能给出了一个定律:

When we spped up one part of a system, the effect on the overall system
performance depends on both how significant this part was and how much is sped up.

大意是:当我们提高系统中某个部分的性能时,对整个系统性能的影响取决于这部分对系统的重要性以及这部分的提升量有多大。

与之相关的公式为:

equation_amdahl_law.jpg
  • Told : 提升前系统运行代码所需要的时间
  • Tnew : 提升后系统运行代码所需要的时间
  • α : 这部分占用总时间的比重
    • 也就是说原来这部分占用时间为 α * Told , 提升后占用的时间为 α * Told / k
  • k : 这部分的提速系数
  • S : 整个系统提升系数

比如这部分消耗总时间的 60%,也就是α = 0.6,当此部分提升系数为3,最终整个系统的提升系数约为1.67。

  • 如果另外一部分提升系数也一样为3,但由于其比重小,导致整个系统提升系数更小。
    • 所以做事要抓重点,明白什么更重要,什么最重要……

还有一点需要注意的是,假设k的值为无穷大,当此部分占用系统60%资源时, 其整个系统的提升系数最多为2.5。 也就是说,并不代表K越大就越好,需要考虑投入与回报比。

为了直观的展示此函数的曲线,我们用 matlab进行绘制如下图(α=0.6):

amdahl_pic.jpg

可以看出,只有前面的线性增长区才是投入与回报成正比。

Concurrency and Parallelism

计算机的发展一直都存在以下两个需求:

  1. concurrency : 多重的,并发的处理能力
  2. parallelism : 处理速度尽量的快

根据以上两个需求将硬件系统分为3个等级,分别由高到低。

Thread-Level Concurrency

并发是宏观上的同时运行任务,并行是真实的同时进行,并行属于并发。

最开始的计算机都是都是由单核处理器通过分时复用来达到宏观上的同时处理任务的能力,这种系统称为单机系统(uniprocessor system)

后来出现了可以同时处理多个任务的多处理系统(multiprocessor),这其中包括多核(multi-core)和超线程(hyperthreading).

  • 多核使得系统可以同时处理多个进程,满足了concurrency的需求
  • 而超线程使得在运行一个进程时,可以使用多线程编程技术使得一个进程运行得更快,满足了parallelism需求。

多核是指在一个单芯片上集成了多个核心,它们具有独立的缓存,也有共用的外部缓存和内存,如下图。

multi_core.jpg

而超线程指的是在一个核心的基础上,其内部有多个寄存器的拷贝(比如有多个PC计数器,寄存器等),这样使得单核可以切换多组寄存器来运行不同的线程。

Instruction-Level Parallelism

现在计算机可以在一个时钟周期执行多条指令,这是在指令执行的维度来提高处理速度。

single-instruction,Multiple-Data(SIMD) Parallelism

处理器提供硬件支持单个指令可以同时处理多个数据,这样也可以提高处理速度。

The importance of acstractions in computer systems

在计算机学科中,需要学会以抽象的方式提现系统的一部分或整体架构,这既能理解其中的概念,还能隐藏其中复杂的细节。

Last Updated 2018-10-14 日 19:32.
Render by hexo-renderer-org with Emacs 26.1 (Org mode 9.1.14)