01:计算机系统漫游
- 编译系统(预处理、编译、汇编和链接)、系统的硬件构成、程序执行和硬件的交互和存储设备
- 操作系统(进程、虚拟内存和文件)、并发和并行(多线程和多指令)
文章目录
1. 编译系统是如何工作的?
-
预处理:hello.c -> hello.i
将#头文件的内容平铺插入源代码中,得到另一种C程序 -
编译:hello.i -> hello.s
词法分析、语法分析、语义分析、中间代码生成及优化等等一系列的中间操作头文件预编译(一般扩展名为.PCH):把较稳定的代码预先编译好放在.pch;之后无需编译。优点:提高编译速度
-
汇编:hello.s -> hello.o
根据指令集将汇编程序 hello.s 翻译成机器指令,且把一系列的机器指令按照固定的规则进行打包,得到可重定位目标文件 hello.o -
链接:hello.o -> hello
将程序中引用到的.o
文件进行合并,得到可执行目标文件动态链接、静态链接
2. 系统的硬件构成
理解这块知识时,可以联想平时用到的实物(主机、显示屏、键盘鼠标等)
2.1 CPU(中央处理单元 / 处理器)
系统上电的瞬间,到系统断电:处理器就不断执行PC指向的指令;然后更新PC,使其指向下一条要执行的指令(指令间并不一定内存相邻)
举个例子:指令为计算两个变量a+b的和
- CPU从内存中读取 a 的值暂存在寄存器 X 中,读取 B 的值暂存在寄存器 Y中;
- 在CPU完成加载操作后,ALU会复制寄存器 X 和 Y 中保存的数值,进行算术运算;
- 最后,得到的结果会保存到寄存器 X 或者寄存器 Y 中(寄存器中原来的数值会被覆盖)
PC(程序计数器)
存放指令地址的存储空间(4字节或8字节)
寄存器堆
寄存器是临时存放数据的空间
ALU(算数/逻辑计算单元)
计算机核心部分 - 计算速度极快,专攻算数与逻辑的计算
2.2 内存(运行内存 / 主存)
主要存放程序指令及数据
- 从物理上讲,内存由随机动态存储器芯片组成;
- 从逻辑上讲,内存可看成一个从零开始的大数组,每个字节都有相应地址
2.3 总线
总线贯穿了整个计算机系统,负责将信息从一个部件传递到另外一个部件
- 内存和处理器间通过总线来进行数据传递
- 通常总线被设计成传送固定长度的字节块(32 位机器,一个字长是 4 个字节; 64 位机器,一个字长是 8 个字节)
2.4 输入输出设备
例如键盘、鼠标、显示器及磁盘等
每个输入输出设备都通过一控制器或适配器与IO 总线相连
控制器与适配器
在IO 设备与 IO 总线之间传递数据,两者封装方式不同
3. 程序执行时是如何和硬件系统交互的?
操作过程: Shell中运行./hello
1)通过键盘输入./hello
字符串,shell 程序会将输入的字符逐一读入寄存器,处理器会把 hello 这个字符串放入内存中
2)当按回车键完成输入时,shell 程序知道我们命令已完成输入,会执行一系列指令来加载可执行文件 hello
3)这些指令将 hello 中的数据和代码从磁盘复制到内存
复制过程将利用 DMA(Direct Memory Access)技术,数据(即要显示输出的
hello , world\n
)可不经过处理器,从磁盘直接到达内存
4)当可执行文件 hello 中的代码和数据被加载到内存中,处理器就开始执行 main函数中的代码
4. 存储设备
数据信息需要在磁盘、内存、处理器以及 IO 设备之间进行搬运。如何缩短信息搬运所花费的时间?
通常,大容量存储设备的存取速度比小容量的慢,运行速度更快设备的价格比低速设备要更贵。
存储设备的层次结构
4.1 寄存器、内存和硬盘
磁盘的容量大概是内存的 1000 倍,而从磁盘上读取一个字花费的时间比从内存中读取的开销大1000 万倍
4.2 高速缓存(cache)
高速缓存介于寄存器文件和内存之间
较新的,处理能力较强的处理器,一般有三级高速缓存(L1 cache、L2 cache 及 L3 cache)
- L1 cache 的访问速度与访问寄存器文件几乎一样快,容量大小为KB级
- L2 cache 的访问速度是 L1 cache 的五分之一
- L3 cache 的容量更大,同样访问速度更慢
5. 操作系统如何管理硬件?
操作系统是应用程序和硬件之间的中间层
所有应用程序对硬件的操作必须通过操作系统完成
操作系统引入了几个抽象的概念
5.1 进程
- 操作系统会跟踪进程运行时所需的所有状态信息,控制进程间上下文的切换;
这种状态信息也称为上下文,例如当前 PC 和寄存器的值,以及内存中的内容等 - 一个进程由多个线程组成,每个线程都运行在进程的上下文中,共享代码和数据
一个微信程序就是一个进程,而我们在微信里一边文字聊天、一边视频聊天、一边传输文件就是三个线程同时进行
5.2 虚拟内存
操作系统为每个进程提供了一个假象(每个进程都独自占用整个内存空间),每个进程看到的内存都是一样的,我们称之为虚拟地址空间
从下往上看,地址递增
- 最下方区域:存放程序的代码和数据(大小固定),该区域内容是从可执行目标文件中加载来的,例如我们多次提到的
- 读写数据区域:存放全局变量
- 堆:可在运行时动态的扩展和收缩
- 共享库:存放共享库的代码和数据(标准库/数学库,例如
printf
函数) - 用户栈:函数调用的本质就是压栈 - 每次函数调用,栈就会增长,函数执行完毕返回时,栈就会收缩(栈的增长方向是从高地址到低地址)
- 最顶部区域:内核保留的区域 - 对应用程序不可见
5.3 文件
- 所有的 IO 设备(键盘、磁盘、显示器、网络),都可以看成文件;
- 系统所有输入和输出都可以通过读写文件完成;
- 系统来看,网络也可以视为一个 IO 设备
6. 并发和并行
如何获得更高的计算能力?
一些高性能服务器芯片,单颗芯片集成的 CPU 数量高达几十个 ~ 上百个。通过增加 CPU 的核心数,可提高系统的性能
6.1 线程级并发
当线程因读取数据进入等待状态,CPU 可执行另一个线程(线程切换只需极少时间)
6.2 指令级并行
现代处理器同时执行多条指令
每条指令从开始到结束大概需要 20+ 个时钟周期,但处理器采用很多技巧可同时处理~100 条指命 => 近几年处理器可保持每个周期24条指令的执行速率
6.3 单指令多数据并行
现代处理器拥有特殊的硬件部件,允许一条指令产生多个并行(SIMD)的操作 - 多是为了提高视频音频执行速度
7. 参考资料
https://github.com/datawhalechina/team-learning-program/tree/master/ComputerSystems