学号:120L022004
目 录
6.2 简述壳Shell-bash的作用与处理流程... - 28 -
6.3 Hello的fork进程创建过程... - 29 -
7.2 Intel逻辑地址到线性地址的变换-段式管理... - 33 -
7.3 Hello的线性地址到物理地址的变换-页式管理... - 34 -
7.4 TLB与四级页表支持下的VA到PA的变换... - 35 -
7.5 三级Cache支持下的物理内存访问... - 36 -
7.6 hello进程fork时的内存映射... - 37 -
7.7 hello进程execve时的内存映射... - 37 -
第1章 概述
1.1 Hello简介
P2P(From Program to Process):GCC编译器驱动程序读取源代码文件hello.c,并且把它翻译成一个可执行文件hello。这个翻译过程可以划分为四个阶段:
预处理阶段:预处理器(cpp)根据以字符 # 开头的命令,修改原始的C程序,将 #include命令包含的头文件/源代码读取并把它直接插入程序文本中。结果就得到了另一个C程序hello.i;
编译阶段:编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序;
汇编阶段:接下来,汇编器(as)将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件hello.o中。它是一个二进制文件;
链接阶段:最后,链接器(ld)将程序与函数库中需要使用的二进制文件进行链接,形成可执行目标程序二进制文件。
之后执行该文件会将该文件加载在内存中,由系统执行。操作系统会使用fork函数形成一个子进程,分配相应的内存资源,使用execve函数加载进程(Process),完成P2P(From Program to Process)过程。
020:hello运行时系统会为其分配对应的虚拟内存空间。Hello读取数据时通过层层存储结构,下一级作为上一级的缓存,使数据可以到达CPU进行处理。系统会删除当前虚拟地址的用户部分已存在的数据结构,为hello创建新的区域结构。程序运行完成后系统会回收hello进程并且删除内存中对应的数据,完成020(From Zero-0 to Zero-0)过程。
1.2 环境与工具
1.2.1 硬件环境
CPU: AMD Ryzen7 4800H AMD64 Architecture @2.90GHz
MEM: 16.0GB DDR4 3200MHz (SODIMM)
Disk: Adata IM2P33F8-512GD 512GiB SSD & Samsung SSD 980 1TiB SSD
1.2.2 软件环境
Microsoft Windows 10 64位
Ubuntu 20.04 LTS 64位
Oracle VM VirtualBox 6.0.12
1.2.3 开发工具
GNU GCC 9.2.0
GNU Make 4.2.1
Visual Studio Code x64
EDB Debugger
GNU GDB
1.3 中间结果
文件名 |
作用 |
hello.c |
源代码 |
hello.i |
hello.c预处理生成的文本文件 |
hello.s |
hello.i编译后得到的汇编语言文本文件 |
hello.o |
hello.s汇编后得到的可重定位目标文件 |
hello |
hello.o链接后得到的汇编语言文本文件 |
hello.elfinfo |
hello的readelf解析输出 |
hello.asm |
hello的objdump反汇编输出 |
hello.o.asm |
hello.o的objdump反汇编输出 |
hello.o.elfinfo |
hello.o的readelf解析输出 |
1.4 本章小结
本章简述了hello的P2P,O2O过程,介绍了编写本文时的工作环境。
第2章 预处理
2.1 预处理的概念与作用
概念:预处理阶段,预处理器(cpp, C Pre-Processer)根据以 # 字符开头的命令,修改原始的C程序。以hello.c为例,第6-8行的 #include类命令告诉cpp预处理器读取系统头文件stdio.h, unistd.h, stdlib.h并把它直接插入到程序文本中。对所有 # 开头的命令处理之后,就得到了另一个C程序,以 .i作为扩展名。
作用:在C语言编译到汇编的阶段之前,预扫描源代码,完成头文件的包含、宏的扩展、条件编译、行控制等对代码结构进行的操作,确定要进行编译的全部代码,丢弃不需编译的代码、注释等,便于编译器后续的编译。
2.2在Ubuntu下预处理的命令
Ubuntu下可以使用gcc并附加参数 -E进行预处理,也可以直接调用cpp预处理器程序进行预处理。如下图:
图 2.1 预处理指令
2.3 Hello的预处理结果解析
图2.2 hello.c(源代码)
图2.3 hello.i(预处理输出)
观察对比源代码与预处理后的代码,我们可以得到以下结果:
- 代码行数增加,由23行增加到3060行,这是由于 #include 指令被递归地替换成了相应头文件内的代码。
- 插入了对应的stdio.h, unistd.h, stdlib.h头文件代码,可以发现在默认