ToB企服应用市场:ToB评测及商务社交产业平台

标题: 步伐人生-Hello’s P2P [打印本页]

作者: 农妇山泉一亩田    时间: 2024-6-22 13:08
标题: 步伐人生-Hello’s P2P


计算机系统


大作业



题     目  步伐人生-Hello’s P2P 
专       业         网络空间安全        
学     号         2022111656
班     级         2203901       
学       生          刘政轩       
指 导 教 师           史先俊          






计算机科学与技术学院

2023年5月

摘  要




本篇论文的目的是解释C语言步伐如何从源代码转换为可实行文件。以hello.c步伐为例,本文具体分析了计算机在生成hello可实行文件的预处理、编译、汇编、链接、进程管理等整个生命周期。本文不仅理论上探讨了这些工具的原理和方法,还实际演示了它们的利用和结果,论述了计算机系统的工作原理和体系布局,帮助读者更深入地理解和掌握C语言步伐的编译和实行过程。



关键词:生命周期;计算机系统;体系布局                           










目  录


第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章 概述

(0.5分)


1.1 Hello简介

P2P:即From Program to Process。指从hello.c(Program)变为运行时进程(Process)。要让hello.c这个C语言步伐运行起来,必要先把它酿成可实行文件,这个变化过程有四个阶段:预处理,编译,汇编,链接,完成后就得到了可实行文件,然后就可以在shell中实行它,shell会给它分配进程空间。
020:即From Zero-0 to Zero-0。指最初内存并无hello文件的相关内容,shell用execve函数启动hello步伐,把假造内存对应到物理内存,并从步伐入口开始加载和运行,进入main函数实行目标代码,步伐结束后,shell父进程回收hello进程,内核删除hello文件相关的数据布局。
1.2 环境与工具

硬件环境:
处理器:12th Gen Intel(R) Core(TM)i5-12500H   2.50 GHz
机带RAM:16.0GB
系统范例:64位利用系统,基于x64的处理器
软件环境:Windows11 64位,VMware,Ubuntu 20.04 LTS
开发与调试工具:Visual Studio 2021 64位;vim objump edb gcc readelf等工具
1.3 中间结果

hello.i         预处理后得到的文本文件
hello.s         编译后得到的汇编语言文件
hello.o        汇编后得到的可重定位目标文件
hello.asm      反汇编hello.o得到的反汇编文件
hello1.asm     反汇编hello可实行文件得到的反汇编文件
1.4 本章小结

本章起首介绍了hello的P2P,020流程,包罗流程的设计思路和实现方法;然后,具体说明白本实验所需的硬件设置、软件平台、开发工具以及本实验生成的各个中间结果文件的名称和功能。



第2章 预处理

(0.5分)


2.1 预处理的概念与作用

2.1.1预处理的概念

预处理步骤是指预处理器在步伐运行前,对源文件进行简单加工的过程。预处理过程主要进行代码文本的替换工作,用于处理以#开头的指令,还会删除步伐中的解释和多余的空白字符。预处理指令可以简单理解为#开头的精确指令,它们会被转换为实际代码中的内容(替换)。
2.1.2预处理的作用

预处理过程中并不直接剖析步伐源代码的内容,而是对源代码进行相应的分割、处理和替换,主要有以下作用:
头文件包含:将所包含头文件的指令替代。
宏定义:将宏定义替换为实际代码中的内容。
条件编译:根据条件判断是否编译某段代码。
其他:如解释删除等。
简单来说,预处理是一个文本插入与替换的过程预处理器。

2.2在Ubuntu下预处理的命令

预处理的命令:gcc -E hello.c -o hello.i


2.3 Hello的预处理结果剖析

在Linux下打开hello.i文件,我们对比了源步伐和预处理后的步伐。结果表现,除了预处理指令被扩展成了几千行之外,源步伐的其他部门都保持不变,说明.c文件简直是被修改过了。

在main函数代码出现之前的大段代码源自于的头文件<stdio.h>  <unistd.h>  <stdlib.h> 的依次睁开。
以 stdio.h 的睁开为例:预处理过程中,#include指令的作用是把指定的头文件的内容包含到源文件中。stdio.h是尺度输入输出库的头文件,它包含了用于读写文件、尺度输入输出的函数原型和宏定义等内容。
当预处理器遇到#include<stdio.h>时,它会在系统的头文件路径下查找stdio.h文件,一样平常在/usr/include目次下,然后把stdio.h文件中的内容复制到源文件中。stdio.h文件中大概还有其他的#include指令,比如#include<stddef.h>或#include<features.h>等,这些头文件也会被递归地睁开到源文件中。


预处理器不会对头文件中的内容做任何计算或转换,只是简单地复制和替换。

2.4 本章小结

本章报告了在linux环境中,如何用命令对C语言步伐进行预处理,以及预处理的寄义和作用。然后用一个简单的hello步伐演示了从hello.c到hello.i的过程,并用具体的代码分析了预处理后的结果。通过分析,我们可以发现预处理后的文件hello.i包含了尺度输入输出库stdio.h的内容,以及一些宏和常量的定义,还有一些行号信息和条件编译指令。

第3章 编译

2分)


3.1 编译的概念与作用

3.1.1编译的概念

       计算机步伐编译的概念是指将用高级步伐设计语言书写的源步伐,翻译成等价的汇编语言格式步伐的翻译过程。
3.1.2编译的作用

       计算机步伐编译的作用是使高级语言源步伐变为汇编语言,进步编程效率和可移植性。计算机步伐编译的基本流程包罗词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等阶段。

3.2 在Ubuntu下编译的命令

编译的命令:gcc -S hello.i -o hello.s


3.3 Hello的编译结果剖析

3.3.1汇编初始部门

在main函数前有一部门字段展示了节名称:


.file               声明出源文件
.text               表现代码节
.section   .rodata    表现只读数据段
.align              声明对指令或者数据的存放所在进行对齐的方式
.string              声明一个字符串
.globl              声明全局变量
.type               声明一个符号的范例
3.3.2 数据部门

(1)字符串步伐有两个字符串存放在只读数据段(.section .rodata)中,如图:

hello.c中唯一的数组是main函数中的第二个参数(即char**argv),数组的每个元素都是一个指向字符范例的指针。由知数组起始所在存放在栈中-32(%rbp)的位置,被两次调用作为参数传到printf中。
如图,分别将rdi设置为两个字符串的起始所在:


(2)参数argc
参数argc是main函数的第一个参数,被存放在寄存器%edi中,由语句

可见寄存器%edi所在被压入栈中,而语句

可知该所在上的数值与立刻数4判断巨细,从而得知argc被存放在寄存器并被压入栈中。
(3)局部变量
步伐中的局部变量只有i,我们根据

可知局部变量i是被存放在栈上-4(%rbp)的位置。

3.3.3全局函数

hello.c中只声明白一个全局函数int main(int arge,.char*argv[]),我们通过汇编代码

可知。

3.3.4赋值利用

hel1o.c中的赋值利用贝有for循环开头的i-0,该赋值利用体如今汇编代码上,则是用mov指令实现,如图:

。由于int型变量i是一个32位变量,利用movl通报双字实现。

3.3.5算术利用

hello.c中的算术利用为for循环的每次循环结束后i++,该利用体如今汇编代码则利用指令add实现,问样,由丁变量i为32位,利用指令addl。指令如下:


3.3.6关系利用

hello.c中存在两个关系利用,分别为:

利用了cmp指令比较立刻数4和参数argc巨细,并且设置了条件码。根据条件码,如果不相等则实行该指令后面的语句,否则跳转到.L2。

同(1),设置条件码,并通过条件码判断跳转到什么位置。

3.3.7控制转移指令

设置过条件码后,通过条件码来进行控制转移,在本步伐中存在两个控制转移:
(1)

判断argc是否为4,如果不为4,则实行if语句,否则实行其他语句,在汇编代码中则表现为如果条件码为1,则跳到.L2,否则实行cmpl指令后的指令。
(2)

在for循环每次结束判断一次i<8,翻译为汇编语言后,通过条件码判断每次循环是否跳转到.L4。而在for循环初始要对i设置为0,如下:

然后直接无条件跳转到.L3循环体。

3.3.8函数利用

(1)main函数
参数通报:该函数的参数为int argc,,char*argv[]。具体参数通报所在和值都在前面论述过。
函数调用:通过利用call内部指令调用语句进行函数调用,并且将要调用的函数所在数据写入栈中,然后自动跳转到这个调用函数内部。main函数里调用了printf、exit、sleep函数。
局部变量:利用了局部变量i用于for循环。具体局部变量的所在和值都在前面论述过。
(2)printf函数
参数通报:printf函数调用参数argv[1],argv[2]。
函数调用:该函数调用了两次。第一次将寄存器%rdi设置为待通报字符串"用法:Hello学号姓名 秒数!\n"的起始所在;第二次将其设置为“Hello %s  %s\n”的起始所在。具体已在前面讲过。利用寄存器%rsi完成对argv[1]的通报,用%rdx完成对argv[2]的通报。
(3)exit函数
参数通报与函数调用:

将rdi设置为1,再利用call指令调用函数。
(4)atoi、sleep函数
参数通报与函数调用:

可见,atoi函数将参数argv[3]放入寄存器%rdi中用作参数通报,简单利用call指令调用。

然后,将转换完成的秒数从%eax通报到%edi中,edi存放sleep的参数,再利用call调用。
(5)getchar函数
无参数通报,直接利用call调用即可。

3.3.9范例转换

atoi函数将宁字符中转换为sleep函数必要的整型参数.
3.4 本章小结

这一章介绍了C编译器如何把hello.i文件转换成hello.s文件的过程,简要说明白编译的寄义和功能,演示了编译的指令,并通过分析生成的hello.s文件中的汇编代码,探讨了数据处理,函数调用,赋值、算术、关系等运算以及控制跳转和范例转换等方面,比较了源代码和汇编代码分别是怎样实现这些利用的。

第4章 汇编

2分)


4.1 汇编的概念与作用

4.1.1汇编的概念

       汇编是指汇编器(as)将包含汇编语言的.s文件翻译为机器语言指令,并把这些指令打包成为一个可重定位目标文件的格式,生成目标文件.o文件。.o文件是一个二进制文件,包含main函数的指令编码。
4.1.2汇编的作用

       汇编就是将高级语言转化为机器可直接辨认实行的代码文件的过程,汇编器将.s 汇编步伐翻译成机器语言指令,把这些指令打包成可重定位目标步伐的格式。 .o 文件是一个二进制文件,它包含步伐的指令编码。
4.2 在Ubuntu下汇编的命令

在Ubuntu系统下,对hello.s进行汇编的命令为:
gcc -m64 -no-pie -fno-PIC -c hello.s -o hello.o

4.3 可重定位目标elf格式

    在shell中输入readelf -a hello.o > hello.elf 指令得到 hello.o 文件的 ELF 格式:

4.3.1生成ELF格式的可重定位目标文件

典型的ELF格式的可重定位目标文件的布局如下:
4.3.2查看ELF格式文件的内容

(1)ELF头
ELF头(ELF header)以一个l6字节的序列开始,这个序列描述了生成该文件的系统的字的巨细和字节顺序。ELF头剩下的部门包含了帮助链接器语法分析息争释目标文件的信息,其中包罗ELF头的巨细、目标文件的范例(如可重定位、可实行或者共享的)、机器范例(如x86-64)、节头部表(section header table)的文件偏移,以及节头部表中条目的巨细和数量。差别节的位置和巨细是有节头部表描述的,其中目标文件中每个节都有一个固定巨细的条目(entry)。ELF头展示如下:

(2)节头(section header)
记载各节名称、范例、所在、偏移量、巨细、全体巨细、旗标、链接、信息、对齐。

(3)重定位节
.rel.text节是一个.text节中位置的列表,当链接器把这个目标文件和其他文件组适时,必要修改这些位置。一样平常而言,任何调用外部函数或者引用全局变量的指令都必要修改,而调用本地函数的指令不需修改。可实行目标文件中不包含重定位信息。如图,必要重定位的内容如下:



(4)符号表
.symtab节中包含ELF符号表,这张符号表包含一个条目的数组,存放一个步伐定义和引用的全局变量和函数的信息。该符号表不包含局部变量的信息。符号表如下:


4.4 Hello.o的结果剖析

4.4.1命令

在shell中输入 objdump -d -r hello.o > hello.asm 指令输出hello.o的反汇编文件,并与第3章的hello.s文件进行对照分析。



4.4.2与hel1o.s的对照分析

(1)增加机器语言
每一条指令增加了一个十六进制的表现,即该指令的机器语言。例如,在hello.s中的一个cmpl指令表现为

而在反汇编文件中表现为

(2)利用数进制
反汇编文件中的所有利用数都改为十六进制。如(1)中的例子,立刻数由hello.s中的$4变为了$0x4,所在表现也由-20(%rbp)变为-0x14(%rbp)。可见只是进制表现改变,数值未发生改变。
(3)分支转移
反汇编的跳转指令中,所有跳转的位置被表现为主函数+段内偏移量这样确定的所在,而不再是段名称(例如.L3)。例如下面的jmp指令,反汇编文件中为

而hello.s文件中为

(4)函数调用
反汇编文件中对函数的调用与重定位条目相对应。观察下面两个call指令调用函数,在hello.s中为

而在反汇编文件中调用函数为

在可重定位文件中call后面不再是函数名称,而是一条重定位条目指引的信息。
4.5 本章小结

这一章介绍了汇编的寄义和功能。以Ubuntu系统下的hello.s文件为例,说明白如何把它汇编成hello.o文件,并生成ELF格式的可实行文件hello.elf。将可重定位目标文件改为ELF格式观察文件内容,对文件中的每个节进行简单剖析。通过分析hello.o的反汇编代码(保存在hello.asm中)和hello.s的区别和相同点,让人清楚地理解了汇编语言到机器语言的转换过程,以及机器为了链接而做的准备工作。

第5章 链接

1分)


5.1 链接的概念与作用

5.1.1链接的概念

       链接(linkng)是将各种代码和数据片断收集并组合为一个单一文件的过程,这个文件可被加载(复制)到内存并实行。链接可以实行与编译时(compile time),也就是在源代码被翻译为机器代码时;也可以实行与加载时(load time),也就是步伐被加载器加载到内存并实行时:甚至实行于运行时。
5.1.2链接的作用

       在今世系统中,链接是由叫做链接器(1iker)的步伐自动实行的,它们使得分离编译成为大概。我们不用将一个大型的应用步伐构造为一个巨大的源文件,而是可以把它分解为更小、更好管理的模块,可以独立地修改和编译这些模块。当我们改变这些模块中的一个时,只需简单地重新编译它,并重新链策应用。
5.2 在Ubuntu下链接的命令

在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的格式

    利用readelf剖析hello的ELF格式,得到hello的节信息和段信息:
(1)ELF头(ELF Header)
       hello1.elf中的ELF头与hello.elf中的ELF头包含的信息种类基本相同,以描述了生成该文件的系统的字的巨细和字节顺序的16字节序列Magic开始,剩下的部门包含帮助链接器语法分析息争释目标文件的信息。与hello.elf相比较,hello1.elf中的基本信息未发生改变(如Magic,类别等),而范例发生改变,步伐头巨细和节头数量增加,并且得到了入口所在。


(2)节头
       描述了各个节的巨细、偏移量和其他属性。链接器链接时,会将各个文件的相同段合并成一个大段,并且根据这个大段的巨细以及偏移量重新设置各个符号的所在。



(3)步伐头
步伐头部门是一个布局数组,描述了系统准备步伐实行所需的段或其他信息。




4Dynamic section

(5)Symbol table
       符号表中保存着定位、重定位步伐中符号定义和引用的信息,所有重定位必要引用的符号都在其中声明。



5.4 hello的假造所在空间

    观察步伐头的LOAD可加载的步伐段的所在为0x400000。如图:



利用edb打开hello从Data Dump窗口观察hello加载到假造所在的情况,查
看各段信息。如图:

步伐从所在0x400000开始到0x401000被载入,假造所在从0x4000000x400f0结束,根据5.3中的节头部表,可以通过edb找到各段的信息。
如.interp节,在hello.elf文件中能看到开始的假造所在:

在edb中找到对应的信息:

同样的,我们可以找到如.text节的信息:


5.5 链接的重定位过程分析

5.5.1分析helo与helo.o区别

在Shell中利用命令objdump -d -r hello > hello1.asm生成反汇编文件hello1.asm

与第四章中生成的hello.asm文件进行比较,其差别之处如下:
(1)链接后函数数量增加
       链接后的反汇编文件hello2.asm中,多出了.plt,puts@plt,printf@plt,getchar@plt,exit@plt,sleep@plt等函数的代码。这是因为动态链接器将共享库中hello.c用到的函数加入可实行文件中。

(2)函数调用指令call的参数发生变化
       在链接过程中,链接器剖析了重定位条目,call之后的字节代码被链接器直接修改为目标所在与下一条指令的所在之差,指向相应的代码段,从而得到完备的反汇编代码。

(3)跳转指令参数发生变化
       在链接过程中,链接器剖析了重定位条目,并计算相对间隔,修改了对应位置的字节代码为PLT 中相应函数与下条指令的相对所在,从而得到完备的反汇编代码。


5.5.2重定位过程

重定位由两步组成:
(1)重定位节和符号定义。在这一步中,链接器将所有相同范例的节合并为同一范例的聚合节。然后链接器将运行时的内存所在赋给新的聚合节,赋给输入模块定义的每个节,以及赋给输入模块定义的每个符号。至此步伐中每条指令和全局变量都有唯一的运行内存所在。
(2)重定位节中的符号引用。这一步中链接器修改代码节和数据节中对每个符号的引用,使得它们指向精确的运行时所在。要实行这一步,链接器依赖于可重定位目标模块中称为重定位条目的数据布局。
(3)重定位过程所在计算方法如下:

5.6 hello的实行流程

5.6.1过程

通过edb的调试,一步一步地记载下call命令进入的函数。


(I)开始实行:_start、_libe_start_main
(2)实行main:_main、printf、_exit、_sleep、getchar
(3)退出:exit
5.6.2子步伐名或所在

步伐名               步伐所在
_start                0x4010f0
_libc_start_main       0x2f12271d
main                0x401125
_printf               0x4010a0
_sleep               0x4010e0
_getchar             0x4010b0
_exit                0x4010d0
5.7 Hello的动态链接分析

   动态链接的基本头脑是把步伐按照模块拆分成各个相对独立部门,在步伐运行时才将它们链接在一起形成一个完备的步伐,在调用共享库函数时,编译器没有办法预测这个函数的运行时所在,因为定义它的共享模块在运行时可以加载到恣意位置。正常的方法是为该引用生成一条重定位记载,然后动态链接器在步伐加载的时候再剖析它。延迟绑定是通过GOT和PLT实现的,根据hello.elf文件可知,GOT起始表位置为:0x404000:

GOT表位置在调用dl_init之前0x404008后的16个字节均为0:

调用了dl_init之后字节改变了:

对于变量而言,利用代码段和数据段的相对位置不变的原则去计算精确所在。
对于库函数而言,必要plt、got互助。plt初始存的是一批代码,它们跳转到got所指示的位置,然后调用链接器。初始时got内里存的都是plt的第二条指令,随后链接器修改got,下一次再调用plt时,指向的就是精确的内存所在。接下来实行步伐的过程中,就可以利用过程链接表plt和全局偏移量表got进行动态链接。

5.8 本章小结

本章起首论述了链接的基本概念和作用,展示了利用命令链接生成hello可实行文件,观察了hello文件ELF格式下的内容,利用edb观察了hello文件的假造所在空间利用情况,末了以hello步伐为例对重定位过程、实行过程和动态链接进行分析。

第6章 hello进程管理

1分)

6.1 进程的概念与作用

6.1.1进程的概念

进程的经典定义就是一个实行中步伐的实例。进程是计算机中的步伐关于某数据聚集上的一次运行活动,是系统进行资源分配和调度的基本单元,是利用系统布局的基础。在传统的利用系统中,进程既是基本的分配单元,也是基本的实行单元。
6.1.2进程的作用

进程为步伐提供了一种假象,步伐似乎是独占的利用处理器和内存,处理器似乎是无中断地一条接一条地实行我们步伐中的指令。进程作为一个实行中步伐的实例,系统中每个步伐都运行在某个进程的上下文中。

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

6.2.1 Shell-bash的作用

Shell是一个交互型应用级步伐,也被称为命令剖析器,它为用户提供一个利用界面,接受用户输入的命令,并调度相应的应用步伐。
6.2.2 Shell-bash的处理流程

起首从终端读入输入的命令,对输入的命令进行剖析,如果该命令为内置命令,则立刻实行命令,否则调用fork创建一个新的子进程,在该子进程的上下文中实行指定的步伐。判断该步伐为前台步伐还是后台步伐,如果为前台步伐则等待步伐实行结束,若为后台步伐则将其放回后台并返回。在过程中shell可以接受从键盘输入的信号并对其进行处理。
6.3 Hello的fork进程创建过程

起首用户再shell界面输入指令:./hello 2022111656 刘政轩
Shell判断该指令不是内置命令,于是父进程调用fork函数创建一个新的子进程,该子进程得到与父进程用户级假造所在空间相同的一份副本,包罗代码和数据段、堆、共享库以及用户栈。子进程与父进程最大的区别就是具有差别的PID。在父进程中,fork返回子进程的PID,而在子进程中fork返回0,返回值提供一个明确的方法来分辨步伐是父进程还是在子进程中实行。
6.4 Hello的execve过程

execve函数在当前进程的上下文中加载并运行一个步伐。函数声明如下:
int execve(const char *filename, const char *argv[], const char *envp[]);
execve函数加载并运行可实行目标文件filename,且带参数列表argv和环境变量envp。只有当出现错误时,例如找不到filename,execve才会返回到调用步伐。所以,与fork一次调用返回两次差别,execve调用一次并不返回。main函数运行时,用户栈的布局如图所示:

6.5 Hello的进程实行

hello步伐在运行时,进程提供给应用步伐的抽象有:(1)一个独立的逻辑控制流,它提供一个假象,似乎我们的进程独占地利用处理器;(2)一个私有的所在空问,它提供一个假象,似乎我们的步伐独占地利用CPU内存。
利用系统提供的抽象有:
(1)逻辑控制流。如果想用调试器单步实行步伐,我们会看到一系列的步伐计数器(PC)的值,这些值唯一地对应于包含在步伐的可实行目标文件中的指令,或是包含在运行时动态链接到步伐的共享对象中的指令。这个PC值的序列叫做逻辑控制流,或者简称为逻辑流。一个逻辑流的实行在时间上与另一个流重叠,称为并发流,这两个流被称为并发地运行。
(2)上下文切换。利用系统内核利用一种称为上下文切换的叫高层情势的异常控制流来实现多任务。内核为每一个进程维持一个上下文。上下文就是内核重新启动一个被抢占的进程所需状态。
(3)时间片。一个进程实行它的控制流的一部门的每一时间段叫做时间片。因此,多任务也叫做时间分片。
(4)用户模式和内核模式。处理器通常利用某个控制寄存器中的一个模式位来提供这种功能。当设置了模式位时,进程就运行在内核模式里。一个运行在内核模式的进程可以实行指令集中的所有指令且可以访问系统中的任何内存位置。没有设置模式位时,进程就运行在用户模式中。用户模式中的进程不允许实行特权指令,也不能直接引用所在空间中内核区内的代码和数据。
(5)上下文信息。上下文就是内核重新启动一个被抢占的进程所必要的状态,它由通用寄存器、浮点寄存器、步伐计数器、用户栈、状态寄存器、内核栈和各种内核数据布局等对象的值构成。hello步伐实行过程中,在进程调用execve函数后,进程就为hello步伐分配新的假造所在空间,开始时步伐运行在用户模式中,调用printf函数输出“Hello  2022111656 刘政轩”,之后调用sleep函数,进程进入内核模式,运行信号处理步伐,再返回用户模式,运行过程中,cpu不断切换上下文,使运行过程被切分成时间片,与其他进程交替占用cpu,实现进程的调度。
6.6 hello的异常与信号处理

6.6.1异常的分类


6.6.2异常的处理方式






6.6.3运行结果及相关命令

(1)正常运行状态
在步伐正常运行时,打印8次提示信息,以输入回车为标志结束步伐,并回收进程。


(2)运行时按下Ctrl + C
按下Ctrl + C,Shell进程收到SIGINT信号,Shell结束并回收hello进程。


(3)运行时按下Ctrl + Z
按下Ctrl + Z,Shell进程收到SIGSTP信号,Shell表现屏幕提示信息并挂起hello进程。


(4)对hello进程的挂起可由ps和jobs命令查看,可以发现hello进程确实被挂起而非被回收,且其job代号为1。


(5)在Shell中输入pstree命令,可以将所有进程以树状图表现:


(6)输入kill命令,则可以杀死指定(进程组的)进程:


(7) 输入fg 1则命令将hello进程再次调到前台实行,可以发现Shell起首打印hello的命令行命令,hello再从挂起处继承运行,打印剩下的语句。步伐仍然可以正常结束,并完成进程回收。


(8)不停乱按
       在步伐实行过程中乱按所造成的输入均缓存到stdin,当getchar的时候读出一个’\n’结尾的字串(作为一次输入),hello结束后,stdin中的其他字串会当做Shell的命令行输入。



6.7本章小结

本章的主要内容是探讨计算机系统中的进程和shell,起首通过一个简单的hello步伐,简要介绍了进程的概念和作用、shell的作用和处理流程,还具体分析了hello步伐的进程创建、启动和实行过程,末了,本章对hello步伐大概出现的异常情况,以及运行结果中的各种输入进行了解释和说明。


第7章 hello的存储管理

2分)


7.1 hello的存储器所在空间

7.1.1逻辑所在

在有所在变换功能的计算机中,访问指令给出的所在(利用数)叫逻辑所在,也叫相对所在。要颠末寻址方式的计算或变换才得到内存储器中的物理所在。逻辑所在是由一个段标识符加上一个指定段内相对所在的偏移量,由步伐hello产生的与段相关的偏移所在部门
7.1.2线性所在

线性所在是逻辑所在到物理所在变换之间的一步,步伐hello的代码会产生逻辑所在,在分段部件中逻辑所在是段中的偏移所在,加上基所在就是线性所在。
7.1.3假造所在

步伐访问存储器所利用的逻辑所在称为假造所在。假造所在颠末所在翻译得到物理所在。与实际物理内存容量无关,是hello中的假造所在
7.1.4物理所在

在存储器里以字节为单元存储信息,每一个字节单元给一个唯一的存储器所在,这个所在称为物理所在,是hello的实际所在或绝对所在。
7.2 Intel逻辑所在到线性所在的变换-段式管理

段式管理是指把一个步伐分成多少个段进行存储,每个段都是一个逻辑实体。段式管理是通过段表进行的,包罗段号(段名)、段出发点、装入位、段的长度等。步伐通过分段划分为多个块,如代码段、数据段、共享段等。
一个逻辑所在是两部门组成的,包罗段标识符和段内偏移量。段标识符是由一个16位长的字段组成的,称为段选择符。其中前13位是一个索引号,后3位为一些硬件细节。索引号即是“段描述符”的索引,段描述符具体所在描述了一个段,很多个段描述符就组成了段描述符表。通过段标识符的前13位直接在段描述符表中找到一个具体的段描述符。
全局描述符表(GDT)整个系统只有一个,它包含:(1)利用系统利用的代码段、数据段、堆栈段的描述符(2)各任务、步伐的LDT(局部描述符表)段。
每个任务步伐有一个独立的LDT,包含:(1)对应任务/步伐私有的代码段、数据段、堆栈段的描述符(2)对应任务/步伐利用的门描述符:任务门、调用门等。
段式管理图示如下:

7.3 Hello的线性所在到物理所在的变换-页式管理

假造内存被构造为一个由存放在磁盘上的N个连续的字节巨细的单元组成的数组。VM系统将假造内存分割,称为假造页,类似地,物理内存也被分割成物理页。利用页表来管理假造页,页表就是一个页表条目(PTE)的数组,每个PTE由一个有效位和一个位所在字段组成,有效位表明白该假造页当前是否被缓存在DRAM中,如果设置了有效位,那么所在字段就表现DRAM中相应的物理页的起始位置,如果发生缺页,则从磁盘读取。
MMU利用页表来实现从假造所在到物理所在的翻译。
下面为页式管理的图示:

7.4 TLB与四级页表支持下的VA到PA的变换

Core i7接纳四级页表的层次布局。CPU产生假造所在VA,假造所在VA传送给MU,MMU利用VPN高位作为TLBT和TLBI,向TLB中探求匹配。如果命中,则得到物理所在PA。如果TLB中没有命中,MMU查询页表,CR3确定第一级页表的起始所在,VPN1确定在第一级页表中的偏移量,查询出PTE,以此类推,终极在第四级页表中找到PPN,与VPO组合成物理所在PA,添加到PLT。工作原理如下:

多级页表的工作原理展示如下:

7.5 三级Cache支持下的物理内存访问

如图为高速缓存存储器构造布局:

高速缓存的布局将m个所在位划分成了t个标记位,s个组索引位和b个块偏移位:

如果选中的组存在一行有效位为1,且标记位与所在中的标记位相匹配,我们就得到了一个缓存命中,否则就称为缓存不命中。如果缓存不命中,那么它必要从存储器层次布局的下一层中取出被请求的块,然后将新的块存储在组索引位指示组中的一个高速缓存行中,具体替换哪一行取决于替换战略,例如LRU战略会替换末了一次访问时间最久远的那一行。
7.6 hello进程fork时的内存映射

当fork函数被当前进程调用时,内核为新进程创建各种数据布局,并分配给它一个唯一的PID。为了给这个新进程创建假造内存,它创建了当前进程的mm_ struct、.区域布局和页表的原样副本。当fork在新进程中返回时,新进程如今的假造内存刚好和调用fork时存在的假造内存相同。当这两个进程中的任何一个。厥后进行写利用时,写时复制机制就会创建新页面,因此,也就为每个进程保持了私有所在空间的抽象概念。

7.7 hello进程execve时的内存映射

execve函数调用驻留在内核区域的启动加载器代码,在当前进程中加载并运行包含在可实行目标文件hello中的步伐,用hello步伐有效地替代了当前步伐。加载并运行hello必要以下几个步骤:
(1)删除已存在的用户区域。删除当前进程假造所在的用户部门中的已存在的区域布局。
(2)映射私有区域。为新步伐的代码、数据、.bss和栈区域创建新的区域布局,所有这些新的区域都是私有的、写时复制的。代码和数据区域被映射为hello文件中的.text和.data区,.bss区域是请求二进制零的,映射到匿名文件,其巨细包含在hello中,栈和堆所在也是请求二进制零的,初始长度为零。
(3)映射共享区域。hello步伐与共享对象1ibc.so链接,libc.so是动态链接到这个步伐中的,然后再映射到用户假造所在空间中的共享区域内。
(4)设置步伐计数器。execve做的末了一件事情就是设置当前进程上下文的步伐计数器,使之指向代码区域的入口点。如图所示:

7.8 缺页故障与缺页制止处理

如果步伐实行过程中发生了缺页故障,则内核调用缺页处理步伐。处理步伐实行如下步骤:
(1)检查假造所在是否合法,如果不合法则触发一个段错误,制止这个进程。
(2)检查进程是否有读、写或实行该区域页面的权限,如果不具有则触发保护异常,步伐制止。
(3)两步检查都无误后,内核选择一个牺牲页面,如果该页面被修改过则将其交换出去,换入新的页面并更新页表。然后将控制转移给hello进程,再次实行触发缺页故障的指令。

7.9本章小结

本章主要介绍了hello的存储器所在空间、intel的段式管理、hello的页式管理,以intel Core i7在指定环境下介绍了假造所在VA到物理所在PA的转换、物理内存访问,分析了hello进程fork时的内存映射、hello进程、execve时的内存映射、缺页故障与缺页制止处理。


第八章 hello的IO管理

8.1 Linux的IO设备管理方法

设备的模型化:文件
设备管理:unix io接口
一个Linux文件就是一个m个字节的序列:B0,B1,…,Bk,…,Bm-1
所有的IO设备都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来实行。这种将设备优雅的映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,称为Unix I/O,这使得所有的输入和输出都能以一种同一且同等的方式来实行。

8.2 简述Unix IO接口及其函数

Unix IO接口:
打开文件:一个应用步伐通过要求内核打开相应的文件,来宣告它想要访问一个IO设备。内核返回一个小的非负整数,叫做描述符,它在后续对此文件的所有利用中标识这个文件。内核记载有关这个打开文件的所有信息。应用步伐只需记着这个描述符。
Linux shell创建的每个进程开始时都有三个打开的文件:尺度输入(描述符为0)、尺度输出(描述符为1)和尺度错误(描述符为2)。头文件<unistd.h>定义了常量STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO,它们可用来取代显式的描述符值。
改变当前的文件位置:对于每个打开的文件,内核保持着一个文件位置k,初始值为0。这个文件位置是从文件开头起始的字节偏移量。应用步伐能够通过实行seek利用,显式的设置文件的当前位置为k。
读写文件:一个读利用就是从文件复制n>0个字节到内存,从当前文件位置k开始,然后将k增加到k+n。给定一个巨细为m字节的文件,当k>=m时实行读利用会触发一个称为end-of-file(EOF)的条件,应用步伐能检测到这个条件。在文件结尾处并没有明确的“EOF符号”。类似的,写利用就是从内存复制n>0个字节到一个文件,从当前文件位置k开始,然后更新k。
关闭文件:当应用完成了对文件的访问之后,它就通知内核关闭这个文件。作为相应,内核释放文件打开时创建的数据布局,并将这个描述符恢复到可用的描述符池中。无论一个进程因为何种缘故原由制止时,内核都会关闭所有打开的文件并释放它们的内存资源。
Unix IO函数:
进程通过调用open函数打开一个已经存在的文件或者创造一个新文件。
int open(char *filename,int flags,mode_t mode);
open函数将filename转换为一个文件描述符,并且返回描述符数字,如果堕落则返回-1。返回的描述符总是在进程中当前没有打开的最小描述符。flags指明进程打算如何访问这个文件,是只读只写还是可读可写。mode指定新文件的访问权限位。
进程通过调用close函数关闭一个打开的文件。
int close(int fd)
若成功则返回0,若堕落则返回-1。关闭一个已关闭的描述符会堕落。
步伐通过调用read和write函数来实行输入和输出。
ssize_t read(int fd,void *buf,size_t n);
若成功则返回读的字节数,若EOF返回0,若堕落返回-1
ssize_t write(int fd,const void *buf,size_t n);
返回:若成功则为写的字节数,若堕落则为-1
read函数从描述符为fd的当前文件位置复制最多n个字节到内存位置buf。
write函数从内存位置buf复制至多n个字节到描述符fd的当前文件位置。
通过调用lseek函数,应用步伐能够显式的修改当前文件位置。

8.3 printf的实现分析

从vsprintf生成表现信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.
字符表现驱动子步伐:从ASCII到字模库到表现vram(存储每一个点的RGB颜色信息)。
表现芯片按照刷新频率逐行读取vram,并通过信号线向液晶表现器传输每一个点(RGB分量)。
printf的函数体:


…是可变形参的一种写法,可以认为是通过栈传参的,所以(char*)(&fmt) + 4是…中第一个参数的所在。注意fmt虽然是一个字符串的首所在,但是这个变量也是有自己的所在的,就是它在栈中的那个所在,所以用&得到它在栈中的所在,然后+4就是第一个参数的所在。
然后是vsprintf函数的函数体:

可以看出是利用格式串和其他参数得到终极要输出的字符串,即格式化。返回的是要输出的字符串的长度。
然后调用write系统函数。这个函数的反汇编内容如下:
write:
mov eax, _NR_write
mov ebx, [esp + 4]
mov ecx, [esp + 8]
int INT_VECTOR_SYS_CALL
可以看到利用int调用制止门,来实现特定的系统服务。它之后调用sys_call函数。sys_call一个call save,保存制止前进程的状态。sys_call将字符串中的字节从寄存器中通过总线复制到显卡的显存中,显存中存储的是字符的ASCII码。字符表现驱动子步伐将通过ASCII码在字模库中找到点阵信息存储到vram(存储每一个点的RGB颜色信息)中。表现芯片会按照一定的刷新频率逐行读取vram,并通过信号线向液晶表现器传输每一个点(RGB分量)。于是字符串就表现在了屏幕上。

8.4 getchar的实现分析

第一次getchar()时,必要人工输入,但是如果输入了多个字符,以后的getchar()再实行时就会直接从缓冲区读取。键盘输入的字符都存到缓冲区内,一旦键入回车,getchar就进入缓冲区读取字符,一次只返回第一个字符作为getchar函数的值,如果有循环或充足多的getchar语句,就会依次读出缓冲区内的所有字符直到’\n’。
getchar函数在stdio.h中声明,代码如下(参考网上的博客,感觉代码内容有点问题,不外头脑应该是没问题的):


bb是缓冲区的开始,int变量n初始化为0,只有在n为0的情况下从缓冲区读入BUFSIZ个字节。返回时如果n大于0,那么返回缓冲区的第一个字符,否则返回EOF。
异步异常-键盘制止的处理:当用户按键时,键盘接口会得到一个代表该按键的键盘扫描码,同时产生一个制止请求。键盘制止服务步伐先从键盘接口取得按键的扫描码,然后根据其扫描码判断用户所按的键并做相应的处理,末了通知制止控制器本次制止结束并实现制止返回。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。

8.5本章小结

本章通过介绍Linux的IO设备管理方法、Unix IO的接口及函数、printf和getchar的实现,让我们对hello实行过程中的IO管理有了一定的熟悉。

结论

0分,必要项,如缺失扣1分,根据内容酌情加分)

hello所履历的过程:
起首由步伐员将hello代码从键盘输入,依次要颠末以下步骤:
1、预处理(cpp)。将hello.c进行预处理,将文件调用的所有外部库文件合并睁开,生成一个颠末修改的hello.i文件。
2、编译(ccl)。将hello.i文件翻译成为一个包含汇编语言的文件hello.s。
3、汇编(as)。将hello.s翻译成为一个可重定位目标文件hello.o。
4、链接(ld)。将hello.o文件和可重定位目标文件和动态链接库链接起来,生成一个可实行目标文件hello。
5、运行。在shel1中输入./hello 2022111656 刘政轩。
6、创建进程。终端判断输入的指令不是shell内置指令,于是调用fork函数创建一个新的子进程。
7、加载步伐。shell调用execve函数,启动加载器,映射假造内存,进入步伐入口后步伐开始载入物理内存,然后进入main函数。
8、实行指令:CPU为进程分配时间片,在一个时间片中,hello享有CPU资源,顺序实行自己的控制逻辑流。
9、访问内存:MU将步伐中利用的假造内存所在通过页表映射成物理所在。
10、信号管理:当步伐在运行的时候我们输入Ctrl+c,内核会发送SIGINT信号给进程并制止前台作业。当输入Ctrl+z时,内核会发送SIGTSTP信号给进程,并将前台作业制止挂起。
11、制止:当子进程实行完成时,内核安排父进程回收子进程,将子进程的退出状态通报给父进程。内核删除为这个进程创建的所有数据布局。

感悟:
通过本次实验,我深切感受到计算机系统的精致和强大,每一个简单的任务都必要计算机的各种复杂的利用来完成,这背后表现出了严谨的逻辑和今世工艺的精良。


附件

文件名

功能

hello.c

源步伐

hello.i

预处理后得到的文本文件

hello.s

编译后得到的汇编语言文件

hello.o

汇编后得到的可重定位目标文件

hello.elf

用readelf读取hello.o得到的ELF格式信息

hello.asm

反汇编hello.o得到的反汇编文件

hello1.asm

反汇编hello可实行文件得到的反汇编文件

hello

可实行文件

(附件0分,缺失 -1分)


参考文献

为完成本次大作业你翻阅的书籍与网站等

[1]   Randal E.Bryant David R.O'Hallaron.深入理解计算机系统(第三版).机械工业出书社,2016.
[2]   https://www.cnblogs.com/buddy916/p/10291845.html
[3]   https://www.cnblogs.com/pianist/p/3315801.html
[4]   https://www.cnblogs.com/fanzhidongyzby/p/3519838.html.
[5]   https://www.cnblogs.com/diaohaiwei/p/5094959.html
[6]   https://blog.csdn.net/spfLinux/article/details/54427494
(参考文献0分,缺失 -1分)




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




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4