程序人生
计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 人工智能
学 号 2021111057
班 级 2103601
学 生 刘凯锋
指 导 教 师 郑贵滨
计算机科学与技术学院
2022年5月
摘 要
hello.c程序是c语言中最简单的一个程序,其往往是初学者最先写的一道程序,然后,在简单代码的背后,确实不寻常,蕴含人类伟大智慧的实现过程。hello.c经过预处理,编译,汇编,链接,最终成为可执行程序hello,这个过程中涉及到了从基于自然语言的高级程序到机器可识别的二进制代码的过程,涉及到虚拟地址到物理地址的转化过程,在shell中键下./hello命令时,系统悄无声息的执行复杂的操作,为何多个程序不会互相影响?为何系统能够同时执行多个线程?秘密藏在系统之中,我们将深入简单命令下的复杂过程,理解hello程序真正精彩的一生。
**关键词:**预处理;编译;汇编;链接;信号;shell
目 录
第1章 概述 - 4 -
1.1 Hello简介 - 4 -
1.2 环境与工具 - 4 -
1.3 中间结果 - 4 -
1.4 本章小结 - 4 -
第2章 预处理 - 5 -
2.1 预处理的概念与作用 - 5 -
2.2在Ubuntu下预处理的命令 - 5 -
2.3 Hello的预处理结果解析 - 5 -
2.4 本章小结 - 5 -
第3章 编译 - 6 -
3.1 编译的概念与作用 - 6 -
3.2 在Ubuntu下编译的命令 - 6 -
3.3 Hello的编译结果解析 - 6 -
3.4 本章小结 - 6 -
第4章 汇编 - 7 -
4.1 汇编的概念与作用 - 7 -
4.2 在Ubuntu下汇编的命令 - 7 -
4.3 可重定位目标elf格式 - 7 -
4.4 Hello.o的结果解析 - 7 -
4.5 本章小结 - 7 -
第5章 链接 - 8 -
5.1 链接的概念与作用 - 8 -
5.2 在Ubuntu下链接的命令 - 8 -
5.3 可执行目标文件hello的格式 - 8 -
5.4 hello的虚拟地址空间 - 8 -
5.5 链接的重定位过程分析 - 8 -
5.6 hello的执行流程 - 8 -
5.7 Hello的动态链接分析 - 8 -
5.8 本章小结 - 9 -
第6章 hello进程管理 - 10 -
6.1 进程的概念与作用 - 10 -
6.2 简述壳Shell-bash的作用与处理流程 - 10 -
6.3 Hello的fork进程创建过程 - 10 -
6.4 Hello的execve过程 - 10 -
6.5 Hello的进程执行 - 10 -
6.6 hello的异常与信号处理 - 10 -
6.7本章小结 - 10 -
第7章 hello的存储管理 - 11 -
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 -
7.9动态存储分配管理 - 11 -
7.10本章小结 - 12 -
第8章 hello的IO管理 - 13 -
8.1 Linux的IO设备管理方法 - 13 -
8.2 简述Unix IO接口及其函数 - 13 -
8.3 printf的实现分析 - 13 -
8.4 getchar的实现分析 - 13 -
8.5本章小结 - 13 -
结论 - 14 -
附件 - 15 -
参考文献 - 16 -
第1章 概述
1.1 Hello简介
Hello的P2P(从程序到进程)
程序员编写hello.c,hello.c在经过预处理器cpp后,成为修改后的源程序hello.i,经过编译器ccl编译得到汇编文件hello.s,汇编器as进行汇编得到可重定位目标文件hello.o,经过链接器ld得到可执行目标文件hello。在运行时,操作系统将其加载到计算机内存,读取可执行文件信息,创建(fork())一个进程并分配一定数量的内存空间及计算资源,子进程开始执行execve(),在子进程的上下文中加载并执行hello。
Hello的020
操作系统在调用完execve()执行hello程序后,会为hello进程映射一份虚拟内存,hello进入程序入口后,hello的相关数据被载入物理内存中,分配时间片,分配逻辑控制流等,hello运行结束后,成为zombie进程,之后shell会负责回收。删除hello的相关数据结构。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
使用的软件环境:VirtualBox虚拟机 Ubuntu20.04 LTS
硬件环境:AMD Ryzen7 5800H处理器 16 G RAM 512 G HD Disk
开发工具:gcc,edb,gdb
1.3 中间结果
列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。
文件名 | 作用 |
---|---|
hello.c | hello源文件 |
hello.i | hello修改后的源程序 |
hello.s | hello的汇编文件 |
hello.o | hello的可重定位目标文件 |
hello | hello的可执行文件 |
elfheader | hello.o的ELF头 |
sectionheader | hello.o的节头部表 |
relohello | hello.o的重定位节 |
hellosymbol | hello.o的符号表 |
helloass | hello.o的反汇编 |
helloelfhead | hello的节头部表 |
disassem | hello的反汇编 |
1.4 本章小结
本章主要介绍了shell执行hello程序的过程,以及进行实验所需的环境和工具。
第2章 预处理
2.1 预处理的概念与作用
预处理的概念:预处理器根据以字符#开头的命令,比如一些宏定义,条件编译,include<.h>等命令修改原始的C程序
预处理的作用:
- 将源文件中“#include”格式包含的文件复制到编译的源文件中
- 将#define用实际值替换
- 修改条件编译指令
- 使编写的程序更便于阅读,修改,移植和调回,同时有利于模块化设计
2.2在Ubuntu下预处理的命令
图2.1:ubuntu下预处理命令
预处理命令: gcc -E hello.c -o hello.i或者cpp hello.c -o hello.i
2.3 Hello的预处理结果解析
图2.2:hello.i内容
查看hello.i文件,发现多了很多宏展开以及头文件的内容,但原有的信息仍有保留,如上图。
2.4 本章小结
本章介绍了C程序预处理的概念和作用,并演示了在Ubuntu下利用gcc对C文件进行预处理的过程,分析了.c文件和.i文件的异同。
第3章 编译
3.1 编译的概念与作用
编译的概念:编译器将预处理文件(hello.i)翻译成汇编文件(hello.s)的过程,在此过程中编译器经过一系列的词法分析和语法分析,并根据优化等级进行优化后生成相应的汇编语言程序,汇编语言文件是一个文本文件。
编译的作用:编译可以将源程序翻译后成为优化后的汇编代码,在这个阶段还可以对源程序进行语法检查,调试,修改,覆盖,优化等操作,以及一些嵌入式汇编的处理。
3.2 在Ubuntu下编译的命令
图3.1 利用gcc对hello.i进行编译
编译命令:gcc -S hello.i -o hello.s
3.3 Hello的编译结果解析
汇编语言开头符号代表含义如下表:
.file | 程序源文件 |
---|---|
.text | 代码段,立即数也存放在这里 |
.section | 到节头部表的索引 |
.rodara | 存放只读变量 |
.align | 对齐 |
.type | 类型,数据或者函数 |
.global | 全局变量 |
.string | 字符串 |
3.3.1 数据
- 常量
1.1字符串常量
在hello.s中寻找.rodata位置,此位置上写着printf()中的字符串常量和格式串
图3.2 .rodata节的字符串
如图3.2,”Hello %s %s \n”为字符串常量,存放在.rodata段中
1.2 数字常量
图3.3 .text段的立即数
此处的立即数8为常量,存放在.text段
2.变量
图3.3 变量
如图3.3,-32(%rbp)内存储数据为一变量
3.3.2 全局函数
图3.4 全局函数在汇