哈工大计算机系统大作业 程序人生-Hello’s P2P
计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 计算机与电子通信
学 号 2023111772
班 级 23L0503
学 生 张哲瑞
指 导 教 师 刘宏伟
计算机科学与技术学院
2024年5月
摘 要
本文以“程序人生-Hello's P2P”为主题,详细描述了从C语言程序hello.c到可执行文件hello的完整生命周期,涵盖了预处理、编译、汇编、链接、进程管理、存储管理及I/O管理等计算机系统的核心环节。通过具体实验步骤和理论分析,展示了程序如何在Linux环境下被转化为可执行文件,并最终由操作系统加载执行。文章还探讨了进程创建、动态链接、地址转换、异常处理等关键技术,并结合实验以及截图进行了验证。此外,还对printf和getchar等函数的实现机制进行了深入分析。
关键词:计算机系统;程序生命周期;进程管理;存储管理;动态链接;I/O管理
(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)
目 录
第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指的是From Program to Process,即将hello.c(program)经过预处理(hello.i)、编译(hello.s)、汇编(hello.o)、链接变为可执行文件hello,然后可以在shell中执行,shell通过fork函数为hello创建进程,并使用execve函数执行hello。
Hello的020指的是From Zero-0 to Zero-0,即指在hello程序未运行时,内存中并无hello的相关信息,即开始是Zero。等到hello开始执行后,内存加载hello的相关信息并开始运行,等到hello运行结束,计算机将hello的信息从内存中删除,又变回Zero,达成了From Zero-0 to Zero-0。
1.2 环境与工具
处理器:12th Gen Intel(R) Core(TM) i9-12900HX 2.30 GHz;
内存:32.0 GB;
系统类型:64 位操作系统, 基于 x64 的处理器;
软件环境:VMware;Windows 11;
开发和调试工具:Visual Studio 2022; gdb;gcc;
1.3 中间结果
Hello.i:预处理后的hello代码,是修改了的原程序
Hello.s:编译后的hello代码,是汇编程序
Hello.o:汇编后的hello代码,可重定位目标程序
Hello:链接后的可执行目标程序
1.4 本章小结
本章首先介绍了hello的P2P和020的含义和整个过程,然后介绍了使用的软硬件环境,以及开发与调试工具,最后列出了由hello生成的中间结果文件的名字,文件的作用等。
(第1章0.5分)
第2章 预处理
2.1 预处理的概念与作用
概念:预处理器cpp根据以字符#开头的命令,修改原始的C程序得到另一个C程序,以.i作为文件扩展名。
作用:将#include后面的文件直接插入程序文本中,根据宏定义#define直接在源程序中进行替换,实现了对源代码的转化。
2.2在Ubuntu下预处理的命令
图1.预处理的指令
2.3 Hello的预处理结果解析
使用vim查看hello.c与hello.i,可以发现hello.i较hello.c在main函数前多了许多内容,这些多的内容就是预处理时将#include后面的文件直接插入程序文本的内容
图2.hello.c
图3.hello.i
2.4 本章小结
本章先介绍了预处理的概念和作用,即预处理是指预处理器cpp根据以字符#开头的命令,修改原始的C程序得到另一个C程序,以.i作为文件扩展名的过程;接着在linux系统下对hello.c进行了预处理,得到了hello.i,为下一步编译做好了准备。
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
概念:编译是指编译器ccl将文本文件hello.i翻译成文本文件hello.s,它包含了一个汇编语言程序。
作用:编译器将产生汇编语言文件,并且会检测代码中的语法错误和语义错误,并报错。
3.2 在Ubuntu下编译的命令
(以下格式自行编排,编辑时删除)
应截图,展示编译过程!
图4.编译指令
3.3 Hello的编译结果解析
3.3.1 hello.s的内容
图5 6 7.hello.s
3.3.2 文件说明
图8.文件说明
.file说明了文件名称,.text段保存代码,.section指示把代码划分成若干段,.rodata为只读数据,.align 8用于确保指令或数据的存放地址对齐,此处是8字节对齐,.string声明字符串,.globl声明全局变量main,.type声明main为函数类型。
3.3.3 局部变量,立即数和字符串常量处理
图9.局部变量处理
在第21行对%rsp减32,为局部变量i申请空间
此外看第21行中对于立即数32,在它的前面加上$用以代表它为立即数
图10.字符串常量处理
在第41行,程序使用在3.3.2中已说明的.LC1找到字符串常量并使用
3.3.4 赋值操作
图11.赋值
使用movl指令,此处是将0赋给i
3.3.5 算术操作
图12.加法操作
加法,用addl指令,此处是将i+1
图13.减法操作
此处是减法,将栈减32
3.3.6 关系操作和控制转移
图14.跳转
将cmpl和jle连用,指i0个字节到内存,从当前文件位置k开始,然后将k增加为k + n。给定一个m字节的文件,当k大于等于m时,执行读操作会触发EOF条件,应用程序能检测到这个条件。写操作就是从内存复制n>0个字节到一个文件,从当前文件位置k开始,然后更新k。
5.关闭文件。应用在完成对文件的访问后,会通知内核关闭这个文件,内核将释放打开这个文件时创建的数据结构,并将这个描述符恢复到可用的描述符池中。
-
- 简述Unix IO接口及其函数
int open(const char *pathname, int flags, mode_t mode);
功能:打开文件或设备,返回文件描述符(fd)。
参数:
flags:控制打开方式(如 O_RDONLY、O_WRONLY、O_CREAT、O_TRUNC)。mode:创建文件时的权限(如 0644)。
int close(int fd);
功能:关闭文件
参数:fd是目标文件的描述符
ssize_t read(int fd, void *buf, size_t count);
功能:从 fd 读取最多 count 字节到 buf。
返回值:实际读取的字节数(0 表示 EOF,-1 表示错误)。
ssize_t write(int fd, const void *buf, size_t count);
功能:将 buf 中的 count 字节写入 fd。
返回值:实际写入的字节数(-1 表示错误)。
off_t lseek(int fd, off_t offset, int whence);
功能:移动文件指针。
参数:whence包括SEEK_SET(文件头)、SEEK_CUR(当前位置)、SEEK_END(文件尾)。
8.3 printf的实现分析
[转]printf 函数实现的深入剖析 - Pianistx - 博客园
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
图61.printf程序图
vsprintf的作用就是格式化。它接受确定输出格式的格式字符串fmt。用格式字符串对个数变化的参数进行格式化,产生格式化输出,返回值由i接受,作为要打印的字符串的长度,从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等。字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
本章介绍Linux设备的I/O设备管理方法和Unix IO接口及其函数,并介绍了printf和getchar的实现方法。
(第8章1分)
结论
用计算机系统的语言,逐条总结hello所经历的过程。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
Hello从执行前到执行结束总共经历了以下几个过程:
- 预处理:hello.c通过预处理器cpp根据以字符#开头的命令,修改原始的C程序得到另一个C程序,以.i作为文件扩展名,得到hello.i。
- 编译:hello.i通过编译器ccl将文本文件hello.i翻译成文本文件hello.s,它包含了一个汇编语言程序。
- 汇编:hello.s通过汇编器as将hello.s翻译成机器语言指令,把这些指令打包成可重定位目标程序的格式,并把结果保存在hello.o中。
- 链接:将hello.o变为可执行文件hello
- 准备运行:在shell中输入对应指令./hello 2023111772 zzr 13284965988 3
- 创建进程:shell通过fork函数为hello创建一个新进程
- 执行程序:hello调用execve函数执行程序。
- 加载数据:处理器经过一系列的地址转换,在内存中访问到执行hello所需的数据
- 接收、处理信号:当hello程序发生异常时,hello接收到信号,并作出相应反应,例如接收到SIGINT时程序中断
- 回收进程:当hello程序执行结束时,shell回收该进程
感悟:通过本次大作业,我了解到计算机真的是一个精密的系统,一个简单的hello.c程序的执行,需要软硬件结合才能有条不紊的运行,更何况在现代计算机中,无时无刻不在同时运行着成百上千个比hello更复杂的进程,而它依然游刃有余,这都要多亏了计算机领域的前人,是他们一个个不眠的夜晚,一个个精妙的巧思,才构成了我们如今如此庞大,蓬勃发展的计算机领域
(结论0分,缺失 -1分,根据内容酌情加分)
附件
列出所有的中间产物的文件名,并予以说明起作用。
Hello.i:预处理后的hello代码,是修改了的原程序
Hello.s:编译后的hello代码,是汇编程序
Hello.o:汇编后的hello代码,可重定位目标程序
Hello:链接后的可执行目标程序
(附件0分,缺失 -1分)
参考文献
为完成本次大作业你翻阅的书籍与网站等
[1] linux内核中 逻辑地址、虚拟地址、线性地址和物理地址大扫盲 - 知乎
[2] 深入理解计算机系统,兰德尔 E. 布莱恩特,大卫 R. 奥哈拉论著
(参考文献0分,缺失 -1分)