深入理解计算机系统
B站搬运工:https://www.bilibili.com/video/BV18D4y1d7s3
一个程序从创建到运行需要经历预处理、编译、链接、执行4个过程
1.2 程序被其他程序翻译成不同的格式
(1) 预处理阶段
预处理器根据以字符#开头的命令,修改原始的C程序。比如对#include<stdio.h>的处理就是把“stdio.h”头文件完整的插入到程序文本中生成另一个C程序,该程序以.i为文件扩展名。也就是hello.i文件
(2) 编译阶段
通过汇编器 (ccl) 修改hello.i文件生成汇编程序hello.s,也就是把源程序编译为汇编程序。hello.s文件中的部分内容如下图所示:
(3) 汇编阶段
汇编器 (as) 将hello.s翻译成机器码。生成hello.o文件
(4) 链接阶段
比如hello文件调用了printf函数,printf函数存在于一个名为printf.o的单独的预编译好了的目标文件中,这种文件需要以某种方式合并到hello.o程序中,链接器就是负责这种合并。结果得到hello文件,这就是一个可执行目标文件。
通过预处理,编译,汇编,链接的操作过程,hello.c程序先后转变为hello.i, hello.s, hello.o, 最后生成hello可执行程序。
1.4 处理器读并解释存储在内存中的指令
1.4.1 系统的硬件组成
典型计算机系统的硬件组成主要包括4部分:总线、I/O设备、主存、处理器。
寄存器是CPU的内部组成单元,是CPU运算时取指令和数据的地方,速度很快,寄存器可以用来暂存指令、数据和地址
按照距离CPU的远近排序:寄存器、缓存、内存
1.5 高速缓存至关重要
程序的加载就是从磁盘到处理器,这个过程好需要经过主存。程序的执行可以说是一个不断复制的过程,复制的快慢决定了整个程序执行的开销。为了缩短处理器和主存、磁盘之间的速度差异,利用高速缓存 (缓存距离处理器的距离比较近) 提前将待执行的程序复制到缓存里进而缩短程序执行的开销。这就是高速缓存存在的意义。
比较新的系统一般是有3级高速缓存:L1、L2和L3。
为什么CPU缓存会分为一级缓存L1、L2、L3?有什么意义?
其实缓存的意义很广泛:电脑整机最大的缓存可以体现为内存条、显卡上的显存就是显卡芯片所需要用到的缓存、硬盘上也有相对应的缓存、CPU有着最快的缓存(L1、L2、L3缓存等),缓存就是数据交换的缓冲区(称作Cache)。缓存往往都是RAM(断电即掉的非永久储存),它们的作用就是帮助硬件更快地响应。
(1) CPU缓存是什么?
CPU缓存的定义为CPU与内存之间的临时数据交换器,它的出现是为了解决CPU运行处理速度与内存读写速度不匹配的矛盾——缓存的速度比内存的速度快多了。CPU缓存一般直接跟CPU芯片集成或位于主板总线互连的独立芯片上。(现阶段的CPU缓存一般直接集成在CPU上)CPU往往需要重复处理相同的数据、重复执行相同的指令,如果这部分数据、指令CPU能在CPU缓存中找到,CPU就不需要从内存或硬盘中再读取数据、指令,从而减少了整机的响应时间。
(2) 三级缓存(L1、L2、L3)是什么?
以近代CPU的视角来说,三级缓存(包括L1一级缓存、L2二级缓存、L3三级缓存)都是集成在CPU内的缓存,它们的作用都是作为CPU与主内存之间的高速数据缓冲区,L1最靠近CPU核心;L2其次;L3再次。运行速度方面:L1最快、L2次快、L3最慢;容量大小方面:L1最小、L2较大、L3最大。CPU会先在最快的L1中寻找需要的数据,找不到再去找次快的L2,还找不到再去找L3,L3都没有那就只能去内存找了。L1、L2、L3可以说是各有特点,下面我们就分开来讲一下。
1.6 存储设备形成层次结构
1.7 操作系统管理硬件
操作系统就是应用程序和硬件之间的一层软件,应用程序都是通过操作系统来对硬件进行操作。
(1) 操作系统的两个基本功能:
1.7.1 进程
(1) 什么是进程
进程是操作系统对一个正在运行的程序的一种抽象。从一个进程到另一个进程的转换是由操作系统内核管理。内核不是一个单独的进程,它是系统管理全部进程所用代码和数据结构的集合。
(2) shell进程和hello进程的上下文切换
注意Linux系统中没有线程的概念。Linux中的线程就是轻量级的进程
1.7.2 线程
线程是进程执行的一个实体。线程区别于进程主要是线程之间共享地址内存空间。
1.7.3 虚拟内存
虚拟内存是一个抽象的概念,它使得每个进程认为自己独占地使用内存。每个进程看到的内存都是一样的,即虚拟地址空间。在Linux系统中,地址空间最上面的区域是留给操作系统中的代码和数据的,对所有进程都一样;地址空间的地步区域存放用户进程定义的代码和数据。
内存管理
在C++中,内存分成5个区,他们分 别是堆、栈、自由存储区、全局/静 态存储区和常量存储区。
1.7.4 文件
文件就是字节序列,仅此而已
1.8 系统之间通过网络通信
1.9 重要主题
1.9.1 Amdahl定律
Amdahl定律的主要观点——想对一个系统进行显著的加速,必须提升全系统中相当大的部分的速度。
1.9.2 并发和并行
如果有两个进程,两个CPU,两个这两个进程同时执行叫做并行。如果有3个进程,这三个进程交替执行叫做并发。
(1) 线程级并行
超级线程:允许一个CPU执行多个控制流的技术。
(2) 指令级并行
在较低的抽象层次上,现代处理器可以同时执行多条指令的属性称为指令级并行。
(3) 单指令、多数据并行
一条指令可以产生多个可并行执行的操作。
第一部分 程序结构和执行
第2章 信息的表示和处理
1字=2字节=16位(比特)
三种重要的数字表示:
2.1.1 十六进制表示法
2.1.2 字数据的大小
int类型可以表示的数据范围是
−
2
31
∼
2
31
−
1
-2^{31} \sim 2^{31}-1
−231∼231−1(因为存在符号位)
1GB大概可以存储的字符数为
2
30
2^{30}
230
2.1.3 寻址和字节顺序
(1) 数据的存储
一个int类型的数据是由4个字节组成,多字节对象在计算机内是被存储为连续的字节序列。假如一个变量x地址为0x100,那么这个数据x将被存储在内存的0x100、0x101、0x102、0x103位置。
(2) 字节顺序:小端法和大端法
2.1.4 表示字符串
2.1.5 表示代码
2.1.6 布尔代数简介
2.1.7 C语言中的位级运算
右移 右移分为逻辑右移和算术右移;逻辑右移在左端补k个0,算术右移在左端补k个最高有效位。
2.2 整数表示
https://www.jianshu.com/p/35cf507ebe7f
(1) 如何求正数、负数的补码
计算机中的有符号数是以补码的形式表示的。正数的补码就是其本身;负数的补码是原码取反加1
(2) int类型和char类型
https://blog.csdn.net/unix21/article/details/8606684?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-3.control&dist_request_id=1332037.9671.16191643855811093&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-3.control
2.2.1 整形数据类型
C/C++都支持无符号数和有符号数、但是Java只是支持有符号数
2.2.2 无符号数的编码
给定一个无符号的二进制数
x
=
[
x
w
−
1
,
.
.
.
,
x
0
]
x = [x_{w-1}, ..., x_{0}]
x=[xw−1,...,x0],那么其对应的十进制数为
B
2
U
w
(
x
)
=
∑
i
=
0
w
−
1
x
i
2
i
B2U_{w}(x) =\sum_{i=0}^{w-1}x_{i}2^{i}
B2Uw(x)=i=0∑w−1xi2i
2.2.3 补码编码
有符号数的计算机表示形式就是补码。
https://blog.csdn.net/u012209626/article/details/44753185
2.2.4 有符号数和无符号数之间的转换
2.3 整数运算
(1) 正溢出和负溢出
两个正数相加如果相加的结果为负,则是发生了负溢出;
两个负数相加如果相加的结果为正,则是发生了正溢出;
2.4 浮点数
第三章 程序的机器级表示