【深入理解计算机系统】第一章
本文首发于CSDN,同步到博客园
深入理解计算机系统第一章
当前有如下程序
hello.c
#include
int main()
{
printf("Hello, World!\n");
return 0;
}
1.1 编译系统
通过
gcc -o hello hello.c
可以将hello.c
文件编译成可执行文件hello
这个整体过程分为:
- 预处理 Pre-processor(cpp)
- 编译 Compiler(ccl)
- 汇编 Assembler(as)
- 链接 Linker(ld)
预处理
gcc -E hello.c -o hello.i
对hello.c
进行预处理,得到了hello.i
根据#
开头的代码,替换原始程序中的部分
如#include
就会被替换成stdio.h
文件的内容,得到另一个C程序,即hello.c
经过预处理得到了hello.i
编译
gcc -S hello.i -o hello.s
对hello.i
进行编译,得到了hello.s
,其中编译这一阶段包括词法分析,语法分析,语义分析等。
汇编
gcc -c hello.s -o hello.o
对hello.s
进行汇编得到了hello.o
汇编器根据指令集将汇编程序hello.s
翻译成机器指令,并将这一系列的机器指令按固定规则进行打包,得到可重定位目标文件hello.o
(此时已是二进制文件)
链接
gcc hello.o -o hello
在hello.c
中,调用了printf
函数,这是C标准库的函数,printf
函数在名为printf.o
的文件中,这是一个提前编译好的文件,链接器负责将hello.o
和printf.o
根据一定规则进行合并。而正是因为链接器需要根据一定规则将两者进行合并,所以hello.o
称为一个可重定位目标文件。最终经过链接可以得到可执行目标文件hello
,此时得到的hello
可以加载到内存中进行执行
shell
是一个命令解释程序,它输出一个>
来等待命令行的输入,然后执行这个命令,如果这个命令的第一个单词不是shell
内置命令,那么shell
就会假定这是一个可执行文件的名字,然后加载并运行这个文件
1.2 计算机系统的硬件组成
CPU(Central Processing Unit),中央处理器/处理器
PC(Program Count),程序计数器
PC是大小为1个字的存储区域(对于32位机器,1个字为4字节,而64位机器,1个字位8个字节),
存放着某一条指令的地址。
从系统上电的一瞬间,直到系统断电,处理器在不断执行PC指向的指令,然后更新PC,使其指向下一条要执行的指令(下一条指令并不一定和当前执行的指令相邻)
Register File寄存器文件
寄存器文件由一些单字长的寄存器构成,每个寄存器都有自己唯一的名字。
而寄存器可以理解为一个临时存放数据的空间
举个栗子:
计算a+b的和,那么首先处理器从内存中读取a的值暂存到寄存器X中,读取b的值暂存在寄存器Y中,这个操作会将X和Y中原来的数值给覆盖掉。
处理器完成加载的操作后,ALU(Arithmatic/Logic Unit,算术逻辑单元)会从复制寄存器X和Y中保存的数值,进行算术运算,将得到的结果保存在寄存器X或寄存器Y中。
ALU(Arithmatic/Logic Unit,算术逻辑单元)
主存/内存(Main Memory)
处理器在执行程序时,内存主要存放程序指令及数据。
物理上来看,内存是由动态随机存储器(DRAM,Dynamic Random Access Memory)的芯片组成
逻辑上来看,内存可以看成一个从零开始的数组,每个字节都有相应的地址。
总线(Bus)
内存和处理器之间通过总线(内存总线)来进行数据传递,总线贯穿整个计算机系统(系统总线),负责将信息从一个部件传递到另一个部件通常总线被设计成固定长度的字节块,也就是字(word),在各个系统中的字的具体字节数各不相同。
输入输出设备
键盘
鼠标
显示器
磁盘
每个输入输出设备都通过控制器(Controller)或适配器(Adapter)与IO总线相连,控制器和适配器的主要区别是在于它们的封装方式。无论是控制器都是在IO设备和IO总线之间传输数据
图源自:九曲阑干
关于存储器
寄存器、L1cache、L2cache、L3cache、内存、磁盘
从左到右存取速度越来越快,容量越来越大,造价越来越便宜
图源自:九曲阑干