本文分析Hello程序的全生命周期,首先编写hello.c的源程序,然后运行C预处理器进行预处理,创建hello.i文件,运行C编译器。翻译生成汇编语言文件hello.s,然后运行汇编器,翻译成移动的目标文件hello.o,最后运行链接器程序ld把hello.o和系统目标文件一起包含进来创建文件hello可执行文件。当 shell 收到 ./hello 命令时,它会启动一个 fork 函数来创建一个 execve 进程,将 hello 加载到内存中,控制 CPU 中断,切换上下文,以及处理流异常。程序逻辑,最后,结束进程,由父进程回收。hello“生命”的终结
关键词:预处理;编译;汇编;链接;进程;IO管理;存储;
目 录
2.2在Ubuntu下预处理的命令.......................................................................... - 5 -
3.2 在Ubuntu下编译的命令............................................................................. - 6 -
4.2 在Ubuntu下汇编的命令............................................................................. - 7 -
5.2 在Ubuntu下链接的命令............................................................................. - 8 -
5.3 可执行目标文件hello的格式.................................................................... - 8 -
6.2 简述壳Shell-bash的作用与处理流程..................................................... - 10 -
6.3 Hello的fork进程创建过程..................................................................... - 10 -
6.6 hello的异常与信号处理............................................................................ - 10 -
7.1 hello的存储器地址空间............................................................................ - 11 -
7.2 Intel逻辑地址到线性地址的变换-段式管理............................................ - 11 -
7.3 Hello的线性地址到物理地址的变换-页式管理....................................... - 11 -
7.4 TLB与四级页表支持下的VA到PA的变换............................................. - 11 -
7.5 三级Cache支持下的物理内存访问.......................................................... - 11 -
7.6 hello进程fork时的内存映射.................................................................. - 11 -
7.7 hello进程execve时的内存映射.............................................................. - 11 -
7.8 缺页故障与缺页中断处理........................................................................... - 11 -
8.1 Linux的IO设备管理方法.......................................................................... - 13 -
8.2 简述Unix IO接口及其函数....................................................................... - 13 -
第1章 概述
1.1 Hello简介
P2P:程序员编写hello的本机C语言代码,作为程序保存为hello.c,然后在shell中接受预处理、编译、汇编、链接后的可执行文件。在shell中./hello创建进程,加载可执行文件以运行 hello 程序(即产生 hello 进程)
020:Shell 为 Hello 创建一个进程。并加载Hello可执行程序,映射虚拟内存,进入程序列表,将程序加载到物理内存,main函数运行目标代码,CPU分配运行时间。 Hello执行逻辑控制流程,最后Hello正常退出或收到信号后终止。这将导致操作系统停止Hello进程,释放它所占用的所有资源,并返回给Shell,这是一个从无(0)到无(0)的Hello进程。
1.2 环境与工具
硬件环境:
系统:windows10、Ubuntu 20
工具:g++,vim,edb,vscode,objdump
1.3 中间结果
hello.c:C语言源程序
hello.i:hello.c预处理的文本文件
hello.s:hello.i编译后的汇编文件
hello.o:hello.s汇编后的可重定位(relocatable)文件
hello.o.elf.txt:hello.o经过readelf得到的文本文件
hello:可执行文件
hello.elf.txt:hello经readelf得到的文本文件
hello.o.s:hello.o经objdump得到的汇编代码
hello.oo:hello.oo经objdump得到的汇编代码
1.4 本章小结
本章简单介绍了Hello程序的一生,并勾勒出从P2P到020的整个过程。发现学习整个计算机系统与Hello的一生基本相同。 关于实验软硬件环境和采集处理工具,这就是文章的大致大纲
第2章 预处理
2.1 预处理的概念与作用
概念:预处理器根据以字符“#”开头的命令处理hello.c源程序。
作用:根据源代码中的预处理指令修改源代码,将系统头文件中的头文件源代码插入到目标文件中,最终生成hello.i文件
2.2在Ubuntu下预处理的命令
g++ -E -o hello.i hello.c
2.3 Hello的预处理结果解析
行数显著增多且原本的main()在结尾,g++将#include引入的头文件进行了展开
2.4 本章小结
本章简要介绍了预处理的概念和功能。 并对Linux系统下的hello.c文件进行预处理。 从解析出来的hello.i文件可以看出,预处理操作对源文件中包含的头文件进行了扩展和扩展。 并进行其他处理,如替换指定的宏符号,并按指示选择性地编译。
第3章 编译
3.1 编译的概念与作用
概念:编辑器将文本文件hello.i转化为文本文件hello.s,即一个汇编语言程序。
作用:把源程序翻译成目标程序,进行词法分析和语法分析,分析过程中发现有语法错误,给出提示信息。
3.2 在Ubuntu下编译的命令
g++ hello.i -S -o hello.s
3.3 Hello的编译结果解析
3.3.1 文件开头
.file:源文件名
.text:代码段
.rodata:只读数据段
.globl:全局符号
.type:符号main为函数
.string:字符串
.align:对齐方式
(以下格式自行编排,编辑时删除)
3.3.2 数据保存
字符串:6行8行即为两个字符串,都保存在只读数据部分
局部变量:main中声明了局部变量i,保存在栈上
main()的参数argv:保存在栈上
常数(汇编中的立即数):写在汇编指令中
3.3.3 mov指令
移动数据
有movl和movq两种不同长度的mov指令出现
3.3.4 加法
类似的用到了addl,addq
3.3.5 条件
汇编中通过cmp、jmp类(jg)指令实现条件操作
3.3.6 调用函数
Call指令
多次出现在调用各个库函数时
3.4 本章小结
本章提供对汇编指令的简要介绍以及对 Hello 的机器级实现的理解。我们可以找到这些汇编指令与C语言代码语句的对应关系。 同时,根据一个程序的汇编代码,我们也可以还原出相应的C语言程序的大致样子。
第4章 汇编
4.1 汇编的概念与作用
汇编的概念:汇编是指将用汇编语言编写的程序翻译成等效的机器语言程序的翻译器。汇编器输入用汇编语言编写的源程序,输出以机器语言显示的程序对象,即汇编器将输入的汇编命令文件重新打包成可移动的目标文件并将结果保存为 .o 文件,它是对程序指令进行编码的二进制文件。
汇编的作用:它的作用也很明确,即执行从汇编语言文件到可重定位目标文件的转换
4.2 在Ubuntu下汇编的命令
g++ hello.s -c -o hello.o
4.3 可重定位目标elf格式
使用readelf生成elf文件信息hello.o.elf
生成结果完整内容:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 1240 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)