程序人生-Hello’s P2P
计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 计算机科学与技术
学 号 2021113044
班 级 2103101
学 生 方健
指 导 教 师 刘宏伟
计算机科学与技术学院
2022年5月
本文深入的研究了hello的一生,深入研究它是如何从一个源程序hello.c转化为一个可执行文件的,并在shell里面的运行步骤,详细的分析了每一个过程的具体内容,如编译、汇编、链接、重定位等等。
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简介
1.2 环境与工具
X64 CPU;2GHz;2G RAM;256GHD Disk
Windows11 64位以上; Vmware 16;Ubuntu 20.04 ;LTS 64位/优麒麟 64位
Visual Studio 2021 64位;CodeBlocks 64位;vi/vim/gedit/gcc;edb
1.3 中间结果
elf.txt: 可重定位目标文件hello.o导出的ELF文件;
hello_elf.txt:可执行文件hello导出的ELF文件;
objdump_hello.s:可重定位目标文件hello.o反汇编生成的文件
hello_objdump.s:可执行文件hello反汇编生成的文件
1.4 本章小结
本章简单介绍hello程序的一生,介绍了P2P和020过程,然后又介绍我所使用的硬件环境、软件环境和开发调试工具,最后则简述了过程中间生成的中间文件的名字和作用。
第2章 预处理
2.1 预处理的概念与作用
预处理指的是预处理器cpp根据以字符#开头的命令,来修改原始的C程序,最后生成.i文本文件的过程。
1.将源文件中用#include 形式声明的文件复制到新的程序中;
4.预编译程序可以识别一些特殊符号,预编译程序对于在源程序中出现的这些特殊符号串会用合适值进行替换。
5.预处理还可以帮助程序员节省工作量,提高程序可读性,便于维护。
2.2在Ubuntu下预处理的命令
2.3 Hello的预处理结果解析
2.4 本章小结
本章介绍了预处理的概念和作用,以及预处理的方法,然后展示了.i文件的部分内容,分析了里面内容的由来。
第3章 编译
3.1 编译的概念与作用
编译程序是通过词法分析和语法分析,在确认所有的指令都符合语法规则后,将其翻译成等价的中间代码或汇编代码来表示。编译器cc1将预处理过的文本文件hello.i 翻译转换成汇编文本文件hello.s。
1.语法分析:编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成了符合语法规则的语法单位,方法有自上而下分析法和自下而上分析法两种;
2.中间代码:源程序的一种内部表示,或称之为中间语言。中间代码的作用是使编译程序的结构在逻辑上更为简单明确,特别是使目标代码的优化比较容易实现;
3.代码优化:指对程序进行多种等价变换,使得从变换后的程序出发时能生成更有效的目标代码;
3.2 在Ubuntu下编译的命令
3.3 Hello的编译结果解析
打开我们的hello.s文件我们可以发现汇编代码有一部分是以.作为开头,这些以‘.’开头的行都是指导汇编器和链接器工作的伪指令,通常我们可以忽略这些行,下面给出这些伪指令的含义:如下表
伪指令 |
含义 |
.file |
声明源文件 |
.text |
声明代码节 |
.section |
文件代码段 |
.rodata |
只读文件 |
.align |
数据指令地址对齐方式 |
.string |
声明字符串 |
.globl |
声明全局变量 |
.type |
声明变量类型 |
图3-3-3-1:hello.s汇编代码关于字符串常量的部分
图3-3-3-2:hello.s汇编代码关于全局变量main的部分
解析:这里.globl声明了main是一个全局变量,.type main,@function看出main是一个函数类型
图3-3-3-3:hello.s汇编代码关于函数参数argc、argv的部分
图3-3-3-3-1:hello.s汇编代码关于局部变量i的部分
解析:可以看出-4(%rbp)保存的是变量i的值,初始为0,每次循环加一,循环的条件是i<=8。
图3-3-3-4:hello.s汇编代码关于变量i赋值操作的部分
图3-3-5-1:hello.s汇编代码关于栈指针%rsp算术操作的部分
解析:通过sub将栈指针%rsp减去立即数32,代表栈申请32个字节的空间。
图3-3-5-2:hello.s汇编代码关于栈指针%rsp算术操作的部分
解析:通过add可以将-4(%rbp)里面的值加是立即数1,即i=i+1。
图3-3-6-1 hello.s汇编代码关于控制转移if else的部分
图3-3-6-2 hello.s汇编代码关于控制转移for循环的部分
图3-3-7:hello.s汇编代码关于数组/指针操作argv的部分
图3-3-8-1:hello.s中关于函数printf的调用部分
解析:参数传递:输入参数为1后再执行退出命令,exit(1)表示正常退出,exit(0)表示非正常退出;函数调用:if判断条件满足后被调用;在调用之后程序就会结束进程。
解析:参数传递:输入参数atoi(argv[3]),函数调用:在for循环中被调用,call sleep;调用之后程序延迟。其中其中函数atoi()是把字符串转换成整型数的一个函数。
图3-3-8-4:hello.s关于函数getchar的调用
解析:函数调用:在main中被调用,没有参数传递,getchar()。
解析:main是主函数,有俩参数argc和argv先前已经介绍过,在函数里面最后会return 0,来结束main函数。
3.4 本章小结
本章首先介绍了编译的概念与作业,然后介绍了在Ubuntu下编译的命令,展示了hello.s的内容,最后根据hello.s文件,详细介绍了中编译器是怎么处理C语言的各个数据类型以及各类操作的。
第4章 汇编
4.1 汇编的概念与作用
4.2 在Ubuntu下汇编的命令
4.3 可重定位目标elf格式
由于hello.o文件不能直接打开,因此我们需要输入readelf -a hello.o > ./elf.txt将其转换成elf文件后查看,如下图:
图4-3-1:Ubuntu下导出elf文件展示
4.4 Hello.o的结果解析
命令为:objdump -d -r hello.o > objdump_hello.s
图4-4-1-0:Ubuntu下生成反汇编文件展示
图4-4-1-1:hello反汇编生成的objdump_hello.s
hello.s中的操作数一般是十进制表示的,而objdump_hello.s中的操作数一般是十六进制表示的,如下图:
图4-4-2-2:objdump_hello.s中立即数操作数展示
hello.s中地址使用段名称如 je .L2,而objdump_hello.s中则使用相对偏移地址,如je 2f <main+0x2f>,如下图:
图4-4-2-4:objdump_hello.s中跳转指令展示
图4-4-2-5:objdump_hello.s函数调用展示
图4-4-2-6:hello.s函数调用展示
图4-4-2-7:hello.s中数据访问的变化
图4-4-2-8:objdump_hello.s中数据访问的变化
4.5 本章小结
第5章 链接
5.1 链接的概念与作用
链接是指将多种不同重定位目标文件或静态/动态库的代码和数据部分收集整合起来,修改符号引用,组合并且输出成一个单一可执行目标文件的过程。
5.2 在Ubuntu下链接的命令
5.3 可执行目标文件hello的格式
命令: readelf -a hello > ./hello_elf.txt
解析:节头的内容分析和之前一样,唯一的区别一个就是节的数量多了,由原来的14个变成了现在的27个,多出来的节如下:
节 |
主要作用 |
.interp: |
包含了动态链接器在文件系统中的路径; |
.note .ABI-tag: |
ELF规范中记录的注释部分,包含一些版本信息; |
.gnu .hash: |
符号的哈希表,用于加速查找符号; |
.dynamic .dynsym .dynstr: |
与动态链接符号相关; |
.gnu.version .gnu.version_r: |
与版本有关的信息; |
.init_array .fini_array: |
存放函数指针,其中的函数分别在main函数 之前之后调用,用于初始化和收尾; |
.init .fini: |
存放上述初始化和收尾的代码 |
.eh_frame_hdr |
与异常处理相关。 |
解析:如图所示的节段映射,说明了在链接过程中,将多个代码段与数据段分别合并成一个单独的代码段和数据段,并根据段的大小以及偏移量重新设置各个符号的地址。
解析:分析过程与之前类似,由于对于可执行目标文件来说,仍然会存在重定位信息,因为有些需要动态链接的块还没有被链接,重定位节中就给出了这些符号的相关信息。
5.4 hello的虚拟地址空间
解析:打开edb,加载程序后,打开edb的Date Dump窗口,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。通过查看edb可以发现虚拟地址开始于0x400000,如上图所示。
然后根据节头目表,我们可以通过edb查看各个节的信息,比如.text节,虚拟地址起始于0x4010f0,大小为0x145,如下图所示:
图5-4-3:Data Dump寻找./test节部分
5.5 链接的重定位过程分析
命令:objdump -d -r hello > hello_objdump.s 如图:
图5-5-2-1:hello.o反汇编内容 图5-5-2-2:hello反汇编内容
解析:可以看出来hello反汇编多了很多代码,接下来我会慢慢介绍为什么会多出这些代码
图5-5-2-3:hello反汇编代码关于共享库的部分
解析:在链接之后,链接器会把共享库里面被hello.o里面调用的函数复制进去,所以代码增加了不少。
图5-5-2-4:hello.o反汇编文件函数调用部分
图5-5-2-5:hello反汇编文件函数调用部分
图5-5-2-6:hello.o反汇编./test部分 图5-5-2-7:hello反汇编./test部分
分析:发现左方的.text段只有main函数,右方的.text段不仅包含.main,更包含main函数的很多入口函数,如_start之类,所以./test变长了很多。
重定位将合并输入模块。并为每个符号分配运行地址。重定位由两个步骤组成:重定位节与符号定义、重定位节中的符号引用。
1.定位节与符号定义,链接器将相同类型的节合并为同一类型的新的聚合节,此后链接器将运行时内存地址赋值新的聚合节、输入模块定义的每个节,还有输入模块定义的每个符号。
2.重定位节中的符号引用,链接器修改代码节与数据节中对每个符号的引用,使他们指向正确的运行地址,这一步依赖hello.o中的重定位条目。
5.6 hello的执行流程
通过edb的调试记录下每列函数调用call命令进入的函数如下所示:
<_dl_relocate_static_pie> 401120
5.7 Hello的动态链接分析
分析:在elf文件中我们可以找到got pit开头地址为0x404000,在edb中找到它
5.8 本章小结
第6章 hello进程管理
6.1 进程的概念与作用
一个独立的逻辑控制流,它提供一个假象,好像我们的程序独占地使用处理器。
一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用内存系统。
6.2 简述壳Shell-bash的作用与处理流程
作用:Shell执行一系列的读取解析步骤,然后终止。读取步骤读取来自用户的一个命令行。解析步骤将命令行解析,并运行程序。
(2)分析命令行字符串,获取命令行参数,并构造传递给execve的argv向量
(3)检查第一个(首个、第0个)命令行参数是否是一个内置的shell命令
(4)如果不是内部命令,调用fork( )创建新进程/子进程
(5)在子进程中,用步骤2获取的参数,调用execve( )执行指定程序。
(6)如果用户没要求后台运行(命令末尾没有&号)否则shell使用waitpid(或wait等待作业终止后返回。
(7)如果用户要求后台运行(如果命令末尾有&号),则shell返回;
6.3 Hello的fork进程创建过程
6.4 Hello的execve过程
当Hello的进程被创建之后,他会调用execve函数加载并调用程序。exevce函数在被调用时会在当前进程的上下文中加载并运行一个新程序。它被调用一次从不返回,执行过程如下:
2.映射私有区:为 hello 的代码、数据、.bss 和栈区域创建新的区域结构,所有这些区域都是私有的、写时才复制的
3.映射共享区:比如 hello 程序与共享库 libc.so 链接
4.设置 PC:exceve() 做的最后一件事就是设置当前进程的上下文中的程序计数器,使之指向代码区域的入口点
5.execve() 在调用成功的情况下不会返回,只有当出现错误时,例如找不到需要执行的程序时,execve() 才会返回到调用程序
6.5 Hello的进程执行
内核为每个进程维持一个上下文。上下文就是内核重新启动的一个进程所需的状态。这个状态包括通用目的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内核数据结构。
6.6 hello的异常与信号处理
类别 |
原因 |
异步/同步 |
返回行为 |
中断 |
来自I/O设备的信号 |
异步 |
总是返回到下一条指令 |
陷阱 |
有意的异常 |
同步 |
总是返回到下一条指令 |
故障 |
潜在可恢复的错误 |
同步 |
可能返回到当前指令 |
终止 |
不可恢复的错误 |
同步 |
不会返回 |
对于kill -9 12350:直接将SIGKILL发送到12350进程,使其直接终止.
对于CTRL Z:将SIGINT/SIGSTP由内核发送到12350号进程.SIGINT直接终止12350.而SIGSTP将12350号进程进行停止与挂起.
6.7本章小结
本章介绍了进程的相关概念和作用,了解了shell的处理过程,以及如何利用fork创建子进程,介绍了进程调度和内核用户模式切换,好介绍了4种异常和各种信号,最后根据实际操作进行分析。
第7章 hello的存储管理
7.1 hello的存储器地址空间
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
7.2 Intel逻辑地址到线性地址的变换-段式管理
7.3 Hello的线性地址到物理地址的变换-页式管理
7.4 TLB与四级页表支持下的VA到PA的变换
7.5 三级Cache支持下的物理内存访问
7.6 hello进程fork时的内存映射
7.7 hello进程execve时的内存映射
7.8 缺页故障与缺页中断处理
7.9动态存储分配管理
Printf会调用malloc,请简述动态内存管理的基本方法与策略。
7.10本章小结
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
8.2 简述Unix IO接口及其函数
8.3 printf的实现分析
[转]printf 函数实现的深入剖析 - Pianistx - 博客园
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
结论
一学期的计算机系统学习,虽然很累,不过收获真的很大,感谢一学期老师和助教的辛苦付出!
附件
列出所有的中间产物的文件名,并予以说明起作用。
hello.c:源程序
hello.i:经过预处理过后的文件;
hello.s:经过编译生成的汇编文件;
hello.o:汇编生成的可重定位的文件;
hello:通过链接产生的可执行目标文件二进制文件;
elf.txt: 可重定位目标文件hello.o导出的ELF文件;
hello_elf.txt:可执行文件hello导出的ELF文件;
objdump_hello.s:可重定位目标文件hello.o反汇编生成的文件
hello_objdump.s:可执行文件hello反汇编生成的文件
(附件0分,缺失 -1分)
参考文献
为完成本次大作业你翻阅的书籍与网站等
[1] Randal E.Bryant, David O'Hallaron. 深入理解计算机系统[M]. 机械工业出版社.2019.6
[2] shell解析命令行的过程以及eval命令https://www.cnblogs.com/f-ck-need-u/p/7426371.html
[3] printf 函数实现的深入剖析 https://www.cnblogs.com/pianist/p/3315801.html
[4]老师上课讲的PPT
(参考文献0分,缺失 -1分)
程序人生-Hello’s P2P相关推荐
- 哈工大计算机系统2022大作业:程序人生-Hello‘s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机类 学 号 120L022115 班 级 2003007 学 生 王炳轩 指 导 ...
- 哈工大计算机系统大作业:程序人生-Hello’s P2P
题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 120L022028 班 级 2003007 学 生 杨建中 指 导 教 师 吴锐 计算机科 ...
- 2022计算机系统大作业——程序人生-Hello’s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机 学 号 120L021716 班 级 2003005 学 生 蔡泽栋 指 导 ...
- 哈工大计算机系统大作业——程序人生-Hello’s P2P
计算机系统 大作业 题 目程序人生-Hello's P2P 专 业 计算机科学与技术 学 号120L022401 班 级 200300 ...
- 哈工大CSAPP大作业:程序人生-Hello’s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 120L021818 班 级 2003006 学 生 秦 ...
- HIT CS:APP 计算机系统大作业 《程序人生-Hello’s P2P》
HIT CS:APP 计算机系统大作业 程序人生-Hello's P2P Hello的自白 我是Hello,我是每一个程序猿¤的初恋(羞羞--) l却在短短几分钟后惨遭每个菜鸟的无情抛弃(呜呜--), ...
- 【计算机系统】ICS大作业论文-程序人生-Hello’s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机科学与技术专业 学 号 200111026 班 级 20级计算机9班 学 生 陈弘毅 指 导 教 师 郑贵滨 计算机科学与技 ...
- 程序人生-hello`s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机系 学 号 1170300921 班 级 1703009 学 生 *** 指 导 教 师 史先俊 计算机科学与技术学院 20 ...
- HIT-ICS大作业-程序人生Hello‘s P2P
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机类 学 号 120L021311 班 级 2003011 学 生 郭俊诚 指 导 ...
- HIT-ICS2022大作业(程序人生-Hello’s P2P)
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机科学与技术 学 号 班 级 学 生 指 导 教 师 计算机科学与技术学院 202 ...
最新文章
- 全新目标检测范式SparseR-CNN,超详细实战教学(附数据集)
- 王璋等揭示慢性阻塞性肺疾病炎症内型与呼吸道微生物组的关系(IF 21)
- java 下一代,什么是&QUOT;下一代插件&QUOT;对Java
- 【计算理论】图灵机 ( 非确定性图灵机 | 非确定性图灵机指令分析 | 计算过程 | 非确定性指令出现多个分支 | 非确定性图灵机转为计算树 | 计算树 )
- Boost:reference wrapper参考包装的测试程序
- python列表的索引算法_Python-确定列表是否对称的算法
- Java实现Excel导入数据库,数据库中的数据导入到Excel
- 秒杀场景_Sentinel在秒杀场景的应用_05
- Outlook式样界面菜单和页面控制
- php编程模式,PHP编程之-设计模式简单实例
- 双目测距(四)--罗德里格斯变换
- SQL Server数据库的查询语句
- 利用HTML简单语句来制作个人简历
- 常用公差配合表图_车间里常用的测量器具,别说没见过!
- 如何删除360浏览器的桔梗导航
- 大数据处理技术-头歌平台-答案
- 在你的ipad上使用Vscode撸代码(快速操作向)
- iOS设置基于ikev2的协议连接企业虚拟专用网络
- 进神经网络的学习方式(译文)----中
- C++中头文件(.h)和源文件(.cpp)都应该写些什么
热门文章
- 2021数学建模国赛一等奖经验总结与分享
- 亲测可用sqlyog激活注册码
- JAVA实现网页版斗地主_通过Java实现斗地主
- rpg服务器修改数据,ATOM RPG 修改数据方法 怎么修改游戏数据-游侠网
- 复变函数在计算机科学中的应用,复变函数的应用以及发展史
- 成功解决微信浏览器实现自动下载功能
- 计算机软件水平考试中级题目,计算机软考中级考试试题及答案
- netcore读取json文件_NetCore 对Json文件的读写操作
- Java部署斗鱼直播,iOS斗鱼直播项目
- 斗鱼基于etcd和ZooKeeper的注册中心实践案例