一.编译系统的工作流程:
test.cpp
#include <iostream>
using namespace std;
int main()
{
//hahha
cout<<"hello world"<<endl;
return 0;
}
直接生成可执行程序test
g++ -o test test.cpp
深入解析生成可执行程序test的过程
1.g++ -E test.cpp > test.i
这一步生成test.i进行预处理,做了宏的替换,注释的消除,可看见//hahha不见了
2.g++ -S test.cpp
这一步生成test.s,表示生成汇编指令
3.g++ -c test.cpp
这一步生成test.o,将汇编语言变成二进制机器代码,生成目标文件,也就是二进制文件
利用反汇编工具查看这个机器代码的汇编代码:
objdump -d test_data.o
4.g++ test.o -o test
链接目标代码生成可执行程序test
上述编译过程产生了下面的文件
二.CPU结构
中央处理单元(Central Processing Unit , CPU),也称处理器,包含 PC ( 程序计数
器:Program Count )、寄存器堆(Register file)、ALU(算数/逻辑计算单元:Arithmatic/logic Unit)三个部分.
程序计数器 PC:是一个 4 字节或是 8 字节的存储空间,里面存放的是某一条指令的地址。从系统上电的那一瞬间,直到系统断电,处理器就不断地在执行PC 指向的指令,然后更新 PC,使其指向下一条要执行的指令(注意:这个下一条指令与刚刚执行的指令不一定是相邻的)。
寄存器:可以理解为一个临时存放数据的空间。例如计算两个变量 a+b 的和,处理器从内存中读取 a 的值暂存在寄存器 X 中,读取 B 的值暂存在寄存器 Y中,这个操作会覆盖寄存器中原来的数值,处理器完成加载的操作后,ALU(Arithmatic/logic Unit)会从复制寄存器 X 和 Y 中保存的数值,然后进行算术运算,得到的结果会保存到寄存器 X 或者寄存器 Y 中,此时寄存器中原来的数值会被新的数值覆盖。
算数/逻辑计算单元 ALU:计算速度极快,且专攻算数与逻辑的计算,计算机核心部分.
主存(Main Memory),也称为内存、运行内存,处理器在执行程序时,内存主要存放程序指令以及数据。从物理上讲,内存是由随机动态存储器芯片组成;从逻辑上讲,内存可以看成一个从零开始的大数组,每个字节都有相应地址.
内存和处理器之间通过总线来进行数据传递。实际上,总线贯穿了整个计算机系统,它负责将信息从一个部件传递到另外一个部件。通常总线被设计成传送固定长度的字节块,也就是字(word),至于这个字到底是多少个字节,各个系统中是不一样的,32 位的机器,一个字长是 4 个字节;而 64 位的机器,一个字长是 8 个字节.
三.存储设备的层次结构
对于处理器而言,从磁盘上读取一个字所花费的时间开销比从内存中读取的开销大1000 万倍。寄存器文件的只能存储几百个字节的信息,而内存的可以存放几十亿的字节信息(GB 级),从寄存器文件读取数据比从内存读取差不多要快 100 倍。
随着半导体技术的发展,处理器与内存之间的差距还在持续增大,针对处理器和内存之间的差异,系统设计人员在寄存器文件和内存之间引入了高速缓存(cache),比较新的,处理能力比较强的处理器,一般有三级高速缓存,分别为 L1 cache ,L2cache 以及 L3 cache。
L1 cache 的访问速度与访问寄存器文件几乎一样快,容量大小为数万字节(KB 级别);L2 cache 的访问速度是 L1 cache 的五分之一,容量大小为数十万到数百万字节之间;L3 cache 的容量更大,同样访问速度与 L2 cache 相比也更慢。
四.操作系统作用
操作系统看成是应用程序和硬件之间的中间层,所有的应用程序对硬件的操作必须通过操作系统来完成。
这样设计的目的主要有两个:
1 防止硬件被失控的应用程序滥用;
2 操作系统提供统一的机制来控制这些复杂的底层硬件
为了实现上述的功能,操作系统引入了几个抽象的概念。例如:文件是对 IO 设备的抽象;虚拟内存是对内存和磁盘 IO 的抽象;进程是对处理器、内存以及 IO 设备的抽象。
虚拟内存
操作系统为每个进程提供了一个假象,就是每个进程都在独自占用整个内存空间,每个进程看到的内存都是一样的,我们称之为虚拟地址空间 .
虚拟地址空间分布: Linux 的虚拟地址空间,从下往上看,地址是增大的。最下面是 0 地址。
代码区:存储代码的二进制, 特点是只读 共享.
全局区: 内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量,常量等。其生命周期由操作系统控制.
堆区由程序员控制;类实例化之前是不占用堆和栈的,当实例化以后,采用不同方式就可以占用不用内存分区.
栈区由系统控制,在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。存放函数的参数值,局部变量等。
Kernel Memory:内核保留的区域,应用程序代码不能读写这个区域的数据.
所有的 IO 设备,包括键盘,磁盘,显示器,甚至网络,这些都可以看成文件,
系统中所有的输入和输出都可以通过读写文件来完成.
五.多核处理器结构
参考:
【合集】CSAPP-深入理解计算机系统_哔哩哔哩_bilibili