哈工大盘算机体系大作业--步伐人生 Hello‘s P2P

打印 上一主题 下一主题

主题 1001|帖子 1001|积分 3003

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x




盘算机体系


大作业



题     目  步伐人生-Hellos P2P 
专       业  网络空间安全            
学     号  2021113276              
班   级  2103901                 
学       生  刘禹航               
指 导 教 师                     






盘算机科学与技术学院

2023年5月

摘  要

本文遍历了hello.c步伐在Linux体系下的生命周期,通过gcc、objdump、edb等工具对其代码举行预处理、编译、汇编、链接与反汇编并举行分析,同时对hello的进程运行、内存管理等过程的举行探索,以更深入理解Linux体系下的存储层次布局、异常控制流、假造内存等相关内容,更加深入地理解盘算机体系课程的知识。

关键词:盘算机体系;盘算机体系布局;步伐的生命周期;深入理解盘算机体系                                      









目  录


第1章 概述

1.1 Hello简介

1.2 环境与工具

1.3 中间结果

1.4 本章小结

第2章 预处理

2.1 预处理的概念与作用

2.2在Ubuntu下预处理的下令

2.3 Hello的预处理结果解析

2.4 本章小结

第3章 编译

3.1 编译的概念与作用

3.2 在Ubuntu下编译的下令

3.3 Hello的编译结果解析

3.4 本章小结

第4章 汇编

4.1 汇编的概念与作用

4.2 在Ubuntu下汇编的下令

4.3 可重定位目标elf格式

4.4 Hello.o的结果解析

4.5 本章小结

第5章 链接

5.1 链接的概念与作用

5.2 在Ubuntu下链接的下令

5.3 可执行目标文件hello的格式

5.4 hello的假造地址空间

5.5 链接的重定位过程分析

5.6 hello的执行流程

5.7 Hello的动态链接分析

5.8 本章小结

第6章 hello进程管理

6.1 进程的概念与作用

6.2 简述壳Shell-bash的作用与处理流程

6.3 Hello的fork进程创建过程

6.4 Hello的execve过程

6.5 Hello的进程执行

6.6 hello的异常与信号处理

6.7本章小结

第7章 hello的存储管理

7.1 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本章小结

结论

附件

参考文献



第1章 概述

1.1 Hello简介

根据Hello的自白,使用盘算机体系的术语,简述Hello的P2P,020的整个过程。

  • P2P,即program to process。Hello.c文件经过预处理,编译,汇编,链接变为可执行文件,即步伐,打开shell输入./hello,shell通过fork产生子进程,hello成为进程,发生了由步伐到进程的变化。
  • 020,即zero to zero.初始时内存中无hello的有关内容,当hello步伐结束后,hello进程被接纳,内存中与hello有关的数据被删除,再次变为0,实现了由0到0的变化。
1.2 环境与工具

列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
处理器 11th Gen Intel(R) Core(TM) i7-11370H @ 3.30GHz   3.00 GHz
机带 RAM 16.0 GB (15.7 GB 可用)
体系类型 64 位操作体系, 基于 x64 的处理器



1.3 中间结果

文件名
功能
hello.c
源步伐
hello.i
预处理后得到的文本文件
hello.s
编译后得到的可重定位目标文件
hello.o
汇编后得到的可重定位目标文件
hello.elf
用readelf读取hello.o得到的elf文件
hello.asm
反汇编hello.o得到的反汇编文件
hello1.elf
由hello可执行文件生成的.elf文件
hello1.sam
反汇编hello可执行文件得到的反汇编文件
hello
可执行文件

1.4 本章小结

   本章对hello举行了一个总体的概括,首先先容了P2P、020的意义和过程,先容了作业中的硬件环境、软件环境和开发工具,最后简述了从.c文件到可执行文件中间经历的过程。





第2章 预处理

2.1 预处理的概念与作用

(1)预处理的概念
预处理步骤是指步伐开始运行时,预处理器(cpp,C Pre-Processor,C预处理器)根据以字符#开头的下令,修改原始的C步伐的过程,其中 ISO C/C++要求支持的包罗#if、 #ifdef、 #ifndef、 #else、 #elif、 #endif(条件编译)、 #define(宏界说)、 #include(源文件包罗)、 #line(行控制)、 #error(错误指令)、 #pragma(和实现相关的杂注)以及单独的#(空指令)。除此之外,预处理过程还会删除步伐中的注释和多余的空缺字符。预处理通常得到另一个以.i作为拓展名的C步伐。

(2)预处理的作用
  在集成开发环境中,编译,链接是同时完成的。实在,C语言编译器在对源代码编译之前,还必要进一步的处理:预编译。预编译的主要作用如下:
●将源文件中以”include”格式包罗的文件复制到编译的源文件中。
●用实际值替换用“#define”界说的字符串。
●根据“#if”背面的条件决定必要编译的代码。



2.2在Ubuntu下预处理的下令

下令:cpp hello.c  >  hello.i


2.3 Hello的预处理结果解析



打开产生的hello.i文件,可以看到变成了3000多行,新增的内容是预编译产生的,是stdio.h,unistd.h,stdlib.h的展开。
2.4 本章小结


本章先容了预编译的概念和作用,先容了几个常见的预编译指令,通过观察预编译后产生的文件演示了预编译的详细结果。
(第2章0.5分)


第3章 编译


3.1 编译的概念与作用


(1)编译的概念
编译是指C编译器ccl通过词法分析和语法分析,将合法指令翻译成等价汇编代码的过程。   
(2)编译的作用
将高级语言源步伐翻译成目标步伐

     

3.2 在Ubuntu下编译的下令

下令:gcc -S hello.i -o hello.s

3.3 Hello的编译结果解析


3.3.1 数据
(1)常量
①字符串常量
Printf函数中出现的字符串常量"用法: Hello 学号 姓名 秒数!\n"存储在
.rodata只读数据节

②数字常量

存储在.text节中

(3)变量
①全局变量 存储在.data节中
②局部变量 存储在寄存器或栈中


循环条件i=0,可以看出变量i存储在栈中
3.3.2 赋值
对局部变量的赋值由mov指令来完成,根据操作数值大小,后缀分别为b,w,l,q,分别对应1,2,4,8字节。
3.3.3 算术操作
指令
结果
leaq s,d
d=&s
add s,d
d=d+s
sub s,d
d=d-s

 循环变量i的自增操作。
3.3.4 控制转移操作

对应汇编代码

C语言代码标识假如argc!=4执行printf函数,否则不执行。汇编代码使用je条件跳转指令,假如两个数不相称,则跳转到L2位置。
3.3.5 函数操作
 在x86-64体系中,可以通过寄存器最多通报6个整型(即整数和指针)参数。第1~6个参数一次储存在%rdi、%rsi、%rdx、%rcx、%r8、%r9这六个寄存器中,剩下的参数保存在栈当中。

  • main函数
参数通报:传入参数argc和argv[],分别用寄存器%rdi和%rsi存储。
函数返回:设置%eax为0并且返回,对应return 0 。


  • printf函数,sleep函数,exit函数,getchar函数
  
通过call指令实现函数调用

3.4 本章小结

本章主要先容了编译的概念以及过程,编译是将文本文件翻译成汇编语言步伐,为后续将其转化为二进制机器码做准备的过程。并且以hello.s文件为例,先容了编译器怎样处理各个数据类型以及各类操作,验证了大部分数据、操作在汇编代码中的实现。
第4章 汇编

4.1 汇编的概念与作用

(1)汇编的概念
 汇编是指汇编器(assembler)将以.s结尾的汇编步伐翻译成机器语言指令,把这些指令打包成可重定位目标步伐的格式,并把结果保存在以.o结尾的目标文件中的过程。
(2)汇编的作用
汇编就是将高级语言转化为机器可直接辨认执行的代码文件的过程,汇编器将.s 汇编步伐翻译成机器语言指令,把这些指令打包成可重定位目标步伐的格式。
4.2 在Ubuntu下汇编的下令

下令:gcc -m64 -no-pie -fno-PIC -c hello.s -o hello.o

4.3 可重定位目标elf格式

分析hello.o的ELF格式,用readelf等列出其各节的根本信息,特别是重定位项目分析。
输入readelf -a hello.o > hello.elf下令,得到hello.elf文件


  • elf头
以 16字节序列 Magic 开始,其形貌了生成该文件的体系的字的大小和字节次序,ELF 头剩下的部分包罗资助链接器语法分析息争释目标文件的信息,其中包罗 ELF 头大小、目标文件类型、机器类型、节头部表的文件偏移,以及节头部表中条目的大小和数量等相关信息。


  • 节头


  • 重定位节


  • 符号表

4.4 Hello.o的结果解析

输入 objdump -d -r hello.o > hello.asm 下令得到反汇编文件


  • 操作数的表示
hello.s中用十进制表示;hello.o中用十六进制表示


  • 分支转移
hello.s中步伐跳转的地址为段名称,如.L2,.L3等。
而hello.asm中跳转地址为详细指令地址,如main+0x32


  • 函数调用
hello.s中使用call+函数名的指令来举行函数调用,而hello.asm中call背面是函数指令的地址
4.5 本章小结

本章对汇编的概念与作用举行了先容。以hello.s文件在Ubuntu体系下通过将hello.s文件汇编为hello.o文件,并生成hello.o的ELF格式文件hello.elf为例,研究了ELF格式文件的详细布局,比较了hello.o的反汇编代码(保存在hello.asm中

)与hello.s的异同。

第5章 链接

5.1 链接的概念与作用

(1)链接的概念
 链接是指通过链接器(Linker),将步伐编码与数据块收集并整理成为一个单一文件,生成完全链接的可执行目标文件的过程。
(2)链接的作用

  将为了节省源步伐空间而未编入的常用函数文件(如printf.o)举行合并,令分离编译成为可能,淘汰整体文件的复杂度与大小,增加了容错性,同时方便对某一模块举行针对性修改。
5.2 在Ubuntu下链接的下令

下令:ld -o hello -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o hello.o /usr/lib/x86_64-linux-gnu/libc.so /usr/lib/x86_64-linux-gnu/crtn.o

5.3 可执行目标文件hello的格式

分析hello的ELF格式,用readelf等列出其各段的根本信息,包罗各段的起始地址,大小等信息。



  • elf头


  • 节头


  • 步伐头


  • 动态节


  • 符号表

5.4 hello的假造地址空间

使用edb加载hello,查看本进程的假造地址空间各段信息,并与5.3对照分析阐明。  


5.5 链接的重定位过程分析

















相比hello.o,hello中增加了hello.c源文件所用到的库函数,如printf、getchar、atoi等的详细实现,hello中添加了节,如.init、.fini等,hello.o中的相对偏移地址到了hello中变成了假造内存地址,hello.o中跳转以及函数调用的地址在hello中都被更换成了假造内存地址。

链接器在完成符号解析以后,就把代码中的每个符号引用和一个符号界说关联起来。此时,链接器就知道它的输入目标模块中的代码节和数据节简直切大小。然后就开始重定位,将合并输入模块,并为每个符号分配运行时的地址。链接器将全部输入到hello中相同类型的节合并为同一类型的新的节,然后链接器将运行时内存地址赋给新的节,赋给输入模块界说的每个节,以及赋给输入模块界说的每一个符号。当这一步完成时,步伐中的每条指令和全局变量都有唯一的运行时内存地址了。然后是重定位节中的符号引用,链接器会修改hello中的代码节和数据节中对每一个符号的引用,使得他们指向精确的运行地址。
5.6 hello的执行流程



地址
子函数名
401000
_init
401020
.plt
401090
puts@plt
4010a0
printf@plt
4010b0
getchar@plt
4010c0
atoi@plt
4010d0
exit@plt
4010e0
sleep@plt
4010f0
_start
401120
_dl_relocate_static_pie
401125
main
4011c0
_fini

5.7 Hello的动态链接分析



5.8 本章小结

本章分析了可执行文件hello的ELF格式及其假造地址空间,分析了重定位过程、加载以及运行时函数调用次序以及动态链接过程,深入理解了链接和重定位的过程。

6hello进程管理


6.1 进程的概念与作用

进程的经典界说就是一个执行中的步伐的实例。

体系中的每个步伐都运行在某个进程的上下文中。上下文是由步伐精确运行所需的状态组成的。这个状态包罗存放在内存中的步伐的代码和数据,它的栈、通用目的寄存器的内容、步伐计数器、环境变量、以及打开文件形貌符的集合。
6.2 简述壳Shell-bash的作用与处理流程

作用:shell是一种交互型的应用级步伐。它能够吸收用户下令,然后调用相应的应用步伐,代表用户运行其他步伐。

处理流程:shell执行一系列的读/求值步骤,然后终止。读步骤读取来自用户的一个下令行。求值步骤解析下令行,运行对应的步伐。
6.3 Hello的fork进程创建过程

创建进程后,在子进程中通过判断pid即fork函数的返回值,判断处于子进程,则会通过execve函数在当进步程的上下文中加载并运行一个新步伐。execve加载并运行可执行目标文件,且带参数列表argv和环境变量列表envp。只有当出现错误时,execve才会返回到调用步伐。

在execve加载了可执行步伐之后,它调用启动代码。启动代码设置栈,并将控制通报给新步伐的主函数,即可执行步伐的main函数。此时用户栈已经包罗了下令行参数与环境变量,进入main函数后便开始逐步运行步伐。
6.4 Hello的execve过程

创建进程后,在子进程中通过判断pid即fork函数的返回值,判断处于子进程,则会通过execve函数在当进步程的上下文中加载并运行一个新步伐。execve加载并运行可执行目标文件,且带参数列表argv和环境变量列表envp。只有当出现错误时,execve才会返回到调用步伐。

在execve加载了可执行步伐之后,它调用启动代码。启动代码设置栈,并将控制通报给新步伐的主函数,即可执行步伐的main函数。此时用户栈已经包罗了下令行参数与环境变量,进入main函数后便开始逐步运行步伐。
6.5 Hello的进程执行

内核为每个进程维持一个上下文,上下文就是内核重新启动一个被抢占的进程所必要的状态,它由通用寄存器、浮点寄存器、步伐计数器、用户栈、状态寄存器、内核栈和各种内核数据布局等对象的值构成。

一个进程执行它的控制流的一部分的每一时间段叫做时间片。因此,多使命也叫做时间分片。hello步伐执行过程中同样存储时间分片,与操作体系的其他举行并发运行。

在执行过程中,内核可以决定抢占当进步程,并重新开始一个先前被抢占的进程,这个过程称为调度。在此基础上,hello步伐与操作体系其他进程通过操作体系的调度,切换上下文,拥有各自的时间片从而实现并发运行。步伐在涉及到一些操作时,比方调用一些体系函数,内核必要将当前状态从用户态切换到核心态,执行结束后再及时改用户态,从而保证体系的安全与稳定。
6.6 hello的异常与信号处理

hello执行过程中可能会出现的异常有:中断、陷阱、故障和终止,可能产生的信号有SIGINT、SIGQUIT、SIGKILL、SIGTERM、SIGALRM、SIGCHLD、SIGSTOP等。处理方式可能是将步伐挂起等待下一个信号到临,或终止步伐。

  • 乱按

(2)按回车

(3)Ctrl+Z

输入下令ps查看后台进程,可见hello进程并未克制。输入fg下令,hello进程继承执行。
(4)Ctrl+C

Ctrl+C后输入下令ps查看后台步伐发现没有hello进程,阐明Ctrl+C终止了步伐。
6.7本章小结

本章先容了步伐在shell执行及进程的相关概念,阐明了hello步伐在shell中通过fork函数及execve创建新的进程并执行步伐的过程,内核的调度及上下文切换等机制。研究了hello执行过程中各种操作可能引发的异常和信号处理。

7hello的存储管理


7.1 hello的存储器地址空间

逻辑地址空间的格式为“段地址:偏移地址”,比方“23:8048000”,可以转换为物理地址:逻辑地址CS:EA = 物理地址CS × 16 + EA。保护模式下以段形貌符作为下标,通过在GDT/LDT表得到段地址,段地址加偏移地址得到线性地址。

线性地址空间是指一个非负整数地址的有序集合,比方{0,1,2,3……}。在接纳假造内存的体系中,CPU从一个有N = 2n个地址的地址空间中生成假造地址,这个地址空间称为假造地址空间。

而对应于物理内存中M个字节的地址空间{0, 1, 2, 3, …, M-1}则称为物理地址空间。

Intel处理器接纳段页式存储管理,前者将逻辑地址转换为线性地址从而得到假造地址,后者将假造地址转换为物理地址。逻辑地址中的偏移地址必要经过段地址到线性地址的转换变为假造地址,然后通过MMU转换为物理地址,才能找到对应物理内存。
7.2 Intel逻辑地址到线性地址的变换-段式管理


将步伐按内容或过程函数关系分成段,比方步伐段、数据段……以段为单位分配内存,通过地址映射机制,将段式假造地址转换成实际内存物理地址。段的长度由相应的逻辑信息组的长度决定,因而各段长度不等。逻辑地址得到段号、段内地址,再根据段号和段表求出基址,再由基址+段内地址即可得物理地址。
7.3 Hello的线性地址到物理地址的变换-页式管理



页式管理,是将假造地址空间划分为一个一个固定大小的块(称作虚页),同一时候也让实际地址空间也划分为一个一个相同大小的页(称作实页)。
7.4 TLB与四级页表支持下的VA到PA的变换

每次CPU产生一个假造地址,MMU就必须查阅相应的PTE,这显然造成了巨大的时间开销,为了消除这样的开销,MMU中存在一个关于PTE的小的缓存,称为翻译后备缓冲器(TLB)。TLB通过假造地址VPN部分举行索引,分为索引(TLBI)与标记(TLBT)两个部分。这样,MMU在读取PTE时会直接通过TLB,假如不命中再从内存中将PTE复制到TLB。

在以上机制的基础上,假如所使用的仅仅是假造地址空间中很小的一部分,那么仍然必要一个与使用较多空间相同的页表,造成了内存的浪费。所以假造地址到物理地址的转换过程中还存在多级页表的机制:上一级的页表映射到下一级也表,直到页表映射到假造内存,假如下一级内容都未分配,那么页表项则为空,不映射到下一级,也不存在下一级页表,当分配时再创建相应页表,从而节省内存空间
7.5 三级Cache支持下的物理内存访问

首先获取物理地址VA,使用物理地址的CI举行组索引,分别对每路与缓存标记CT举行标志位匹配。若匹配成功且块的标志位为1则命中。然后根据块偏移取出数据并返回。若未到相匹配的块大概标志位为0,则缓存不命中。一级cache向下逐级寻找查询数据。然后向上逐级写入cache。在更新cache的时候,必要判断是否有空闲块。假如有空闲块(即有效位为0)则写入;假如不存在则驱逐一个近来最少使用的块重新写入。
7.6 hello进程fork时的内存映射

shell通过fork为hello创建新进程。当fork函数被当进步程调用时,内核为新进程创建各种数据布局,并分配给hello进程唯一的pid。为了给这个新进程创建假造内存,它创建当进步程的mm_struct、地区布局和样表的原样副本。它将两个进程中的每个页面都标记为只读,并将每个进程中的每个地区布局都标记为写时复制。

当fork在新进程中返回时,新进程如今的假造内存刚好的和调用fork时的假造内存相同。而当这两个进程中任何一个举行写操作时,就会触发一个保护故障。当故障处理步伐注意到保护异常是由于进程试图写私有的写时复制地区中的一个页面而引起的,它就会在物理内存中创建这个页面的一个新副本,更新页表条目指向这个新的副本,然后恢复这个页面的可写权限。当故障处理步伐返回时,CPU重新执行这个写操作,如今在新创建的页面上这个写操作就可以正常执行了。
7.7 hello进程execve时的内存映射

execve函数在当进步程中加载并运行包罗在可执行目标文件hello中的步伐,用hello步伐有效地替代了当前步伐。加载并运行hello必要以下几个步骤:

1、删除当进步程假造地址的用户部分中的已存在的地区。

2、映射私有地区。为新步伐的代码、数据、bss和栈地区创建新的地区布局。全部这些新的地区都是私有的、写时复制的。

3、映射共享地区。假如hello步伐与共享对象(或目标)链接,好比标准C库libc.so,那么这些对象都是动态链接到这个步伐的,然后再映射到用户假造地址空间中的共享地区内。

4、设置步伐计数器(PC)。execve做的最后一件事情就是设置当进步程上下    文中的步伐计数器,使之指向代码地区的入口点。下一次调度这个进程时,它将从这个入口点开始执行。Linux将根据必要换入代码和数据页面。
7.8 缺页故障与缺页中断处理

缺页故障是指当指令引用一个假造地址,在MMU中查找页表时发现与该地址相对应的物理地址不在内存中就会发生故障。

缺页中断处理:缺页处理步伐是体系内核中的代码,选择一个捐躯页,假如这个捐躯页被修改过,那么就将它互换出去,换入新的页并更新页表。当缺页处理步伐返回时,CPU重新启动引起缺页的指令,这条指令再次发送VA到MMU,这次MMU就能正常翻译VA了。

7.9本章小结

   本章主要先容了hello 的存储器地址空间、intel 的段式管理、hello 的页式管理, VA 到PA 的变换、物理内存访问,hello进程fork、execve 时的内存映射、缺页故障与缺页中断处理,对hello的存储管理有了较为深入的解说。



结论

hello一生的经历如下:


  • 编写:由编辑器编写出hello.c


  • 预处理:将hello.c调用的库合并到hello.i中


  • 编译:将hello.i编译成为汇编文件hello.s


  • 汇编:将hello.s会汇编为可重定位目标文件hello.o


  • 链接:将hello.o与其他可重定位目标文件和动态链接库链接成为可执行目标步伐hello


  • 开始运行:在shell中输入下令行./hello 学号 姓名 秒数


  • 创建子进程:shell进程调用fork为其创建子进程


  • 运行步伐:shell调用execve,execve调用启动加载器,加映射假造内存,进入步伐入口后步伐开始载入物理内存,然后进入 main函数


  • 执行指令:CPU为其分配时间片,在一个时间片中,hello享有CPU资源,执行指令


  • 访问内存:MMU将步伐中使用的假造内存地址通过页表映射成物理地址


  • 动态申请内存:printf调用malloc向动态内存分配器申请堆中的内存


  • 异常控制流:假如运行途中键入ctr-c或ctr-z或举行其他操作,则调用shell的信号处理函数举行相应处理


  • 结束:shell父进程接纳子进程,内核删除为hello进程创建的全部数据布局

《盘算机体系》这门课联合《深入理解盘算机体系》这本书向我们先容了一系列的盘算机基础知识,如数据的表示,机器指令,编译体系等知识,详略得当得向我们展示了一幅盘算机底层的图景,这门课程为以后的学习打好了基础,使我感觉受益匪浅。
附件

文件名
功能
hello.c
源步伐
hello.i
预处理后得到的文本文件
hello.s
编译后得到的可重定位目标文件
hello.o
汇编后得到的可重定位目标文件
hello.elf
用readelf读取hello.o得到的elf文件
hello.asm
反汇编hello.o得到的反汇编文件
hello1.elf
由hello可执行文件生成的.elf文件
hello1.sam
反汇编hello可执行文件得到的反汇编文件
hello
可执行文件


参考文献



  • Randal E.Bryant, David O'Hallaron. 深入理解盘算机体系[M]. 机械工业出版社.2018.4
  • CSDN博客 Ubuntu体系预处理、编译、汇编、链接指令
[3] 博客园 从汇编层面看函数调用的实现原理
[4] CSDN博客 ELF可重定位目标文件格式

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表