CSAPP大作业步伐人生

打印 上一主题 下一主题

主题 503|帖子 503|积分 1509

题     目  步伐人生-Hello’s P2P 
专       业   信息安全                    
学     号   2022112503                    
班     级   2203201                    
学       生   孙柯柯                  
指 导 教 师   史先俊                   

摘  要

本论文跟踪了Hello步伐的整个生命周期,从一个C语言步伐,经过预处理、编译、汇编、链接等过程,天生可执行文件,到执行过程中的历程创建、内存管理、异常处理、信号处理、IO管理等诸多环节,即Hello步伐P2P、020的全过程。了解此过程可以加深对计算机系统的明白,也能领会一个简单步伐的精彩一生。
关键词:步伐;历程 ;假造内存;      
目  录


第1章 概述............................................................................................................. - 4 -
1.1 Hello简介........................................................................................................ - 4 -
1.2 情况与工具........................................................................................................ - 5 -
1.3 中心效果............................................................................................................ - 5 -
1.4 本章小结............................................................................................................ - 5 -
第2章 预处理......................................................................................................... - 7 -
2.1 预处理的概念与作用........................................................................................ - 7 -
2.2在Ubuntu下预处理的命令............................................................................ - 7 -
2.3 Hello的预处理效果解析................................................................................ - 7 -
2.4 本章小结............................................................................................................ - 9 -
第3章 编译........................................................................................................... - 10 -
3.1 编译的概念与作用.......................................................................................... - 10 -
3.2 在Ubuntu下编译的命令.............................................................................. - 10 -
3.3 Hello的编译效果解析.................................................................................. - 10 -
3.4 本章小结.......................................................................................................... - 14 -
第4章 汇编........................................................................................................... - 16 -
4.1 汇编的概念与作用.......................................................................................... - 16 -
4.2 在Ubuntu下汇编的命令.............................................................................. - 16 -
4.3 可重定位目标elf格式.................................................................................. - 16 -
4.4 Hello.o的效果解析....................................................................................... - 19 -
4.5 本章小结.......................................................................................................... - 20 -
第5章 链接........................................................................................................... - 21 -
5.1 链接的概念与作用.......................................................................................... - 21 -
5.2 在Ubuntu下链接的命令.............................................................................. - 21 -
5.3 可执行目标文件hello的格式..................................................................... - 21 -
5.4 hello的假造地点空间................................................................................... - 24 -
5.5 链接的重定位过程分析.................................................................................. - 25 -
5.6 hello的执行流程........................................................................................... - 26 -
5.7 Hello的动态链接分析.................................................................................. - 26 -
5.8 本章小结.......................................................................................................... - 27 -
第6章 hello历程管理....................................................................................... - 28 -
6.1 历程的概念与作用.......................................................................................... - 28 -
6.2 简述壳Shell-bash的作用与处理流程....................................................... - 28 -
6.3 Hello的fork历程创建过程........................................................................ - 28 -
6.4 Hello的execve过程.................................................................................... - 28 -
6.5 Hello的历程执行.......................................................................................... - 29 -
6.6 hello的异常与信号处理............................................................................... - 30 -
6.7本章小结.......................................................................................................... - 33 -
第7章 hello的存储管理................................................................................... - 34 -
7.1 hello的存储器地点空间............................................................................... - 34 -
7.2 Intel逻辑地点到线性地点的变换-段式管理............................................... - 34 -
7.3 Hello的线性地点到物理地点的变换-页式管理......................................... - 35 -
7.4 TLB与四级页表支持下的VA到PA的变换................................................ - 36 -
7.5 三级Cache支持下的物理内存访问............................................................ - 37 -
7.6 hello历程fork时的内存映射.................................................................... - 38 -
7.7 hello历程execve时的内存映射................................................................ - 38 -
7.8 缺页故障与缺页停止处理.............................................................................. - 39 -
7.9动态存储分配管理.......................................................................................... - 40 -
7.10本章小结........................................................................................................ - 41 -
第8章 hello的IO管理..................................................................................... - 42 -
8.1 Linux的IO设备管理方法............................................................................. - 42 -
8.2 简述Unix IO接口及其函数.......................................................................... - 42 -
8.3 printf的实现分析.......................................................................................... - 42 -
8.4 getchar的实现分析...................................................................................... - 44 -
8.5本章小结.......................................................................................................... - 44 -
结论........................................................................................................................ - 45 -
附件........................................................................................................................ - 46 -
参考文献................................................................................................................ - 47 -
第1章 概述

1.1 Hello简介

P2P:From Program to Process,即从步伐到可执行步伐的过程,hello.c依次经过预处理、编译、汇编和链接等步调,最终天生可执行文件hello。

P2P的具体过程:
(1)预处理:hello.c步伐从一个C语言源文件经过预处理器处理,天生预处理后的步伐hello.i。
(2)编译:然后编译器将其编译为汇编步伐hello.s。
(3)汇编:汇编器将hello.s中的汇编指令汇编为呆板指令,天生可重定位的目标文件hello.o。
(4)链接:最后经过链接器处理,链接成可执行文件hello
如图:

图1-1. hello.c的P2P过程

020(From zero to zero)即从创建到接纳的过程。
020的具体过程:
(1)首先,对于可执行步伐hello,可以通过shell来运行,shell收到运行Hello步伐的命令,然后调用fork函数创建一个子历程。
(2)然后,调用execve函数,将hello步伐加载到内存。
(3)接着,hello 步伐在正确的上下文中顺利运行。步伐执行期间,操纵系统利用MMU、TLB、多级页表和缓存等技术来进步内存访问服从,并通过硬件输入输出将效果显示在屏幕上。
(4)最后,历程执行完毕,shell对hello历程举行接纳,内核清除该历程的资源,假造空间回到0,hello没有留下痕迹,这便是从0到0的过程。
总结:hello.c步伐从C语言源文件经过一系列过程被天生一个可执行步伐,再通过被创建为一个历程而完成执行,其数据被加载又被清除,即为Hello的P2P和020的过程。
1.2 情况与工具

硬件情况:
   处理器:11th Gen Intel(R) Core(TM) i5-11400H @ 2.70GHz   2.69 GHz
      RAM:16GB
      操纵系统:64位
                       图1-2. 硬件情况

软件情况:
VMware@ Workstation 17 Pro
Ubuntu 20.04.1

                            图1-3 软件情况

开辟与调试工具: gcc, ld,edb,readelf,objdump
1.3 中心效果

hello.i:预处理后的步伐代码文件;
hello.s:编译后的汇编代码文件;
hello.o:汇编后的步伐目标文件;
hello.elf:hello.o的elf输出效果;
hello.asm:hello.o的反汇编;
hello:可执行步伐;
hello2.elf:hello的elf输出效果;
hello2.asm:hello的反汇编;
1.4 本章小结

本章简要介绍了Hello的完整历程,阐述了P2P和020的含义,并阐明了实验情况、工具和产生的中心效果。
第2章 预处理

2.1 预处理的概念与作用

概念:预处理指在步伐源代码被翻译为目标代码的过程中,预处理器对步伐源代码文本举行处理的过程,此过程并不对步伐的源代码举行解析,而是把源代码分割或处理成为特定的符号用来支持宏调用。
作用:
(1)头文件包含:预处理器解析源代码中的#include指令,将指定的头文件内容插入到源代码中。
(2)宏更换:将源代码中的符号更换为界说的效果;
(3)表明删除:删除表明行,减小目标文件大小,进步编译速度。
(4)条件编译:预处理器根据条件编译指令(如#if、#elif、#else)来选择性地编译。
2.2在Ubuntu下预处理的命令

利用gcc -E hello.c -o hello.i举行预处理,其中-E选项告诉编译器只举行预处理而不执行编译和链接
利用ls命令列出文件,可见天生了预处理后的文件hello.i

                       图2-1 预处理过程
2.3 Hello的预处理效果解析

通过文本编辑器检察hello.i文件的内容
(1)开头显示了预处理器在处理源文件 "hello.c" 时的一些信息,比方, # 1 "hello.c" 指令表明该段代码来自于源文件 "hello.c";#command-line 指令显示在命令行中利用编译器时可能会产生一些额外的信息。

图2-2 基本信息
(2)系统头文件的引入过程,比方# 1 "/usr/include/features.h" 1 3 4表示预处理器引入了头文件 /usr/include/features.h。

图2-3 头文件信息
(3)界说了一系列数据类型的别名,将int等数据类型明白界说为了指定大小的类型:

图2-4 数据类型界说
(4)所插入的头文件具体内容,比方extern int fprintf (FILE *__restrict
__stream, const char *__restrict __format, ...);是函数 fprintf 的声明。

图2-5 头文件具体内容
(5)代码的主体部分,经过对比发现,与hello.c的内容险些完全相同,只是将表明部分删除,这也印证了预处理会删除表明这一作用。

                   图2-6 步伐主体
2.4 本章小结

本章对预处理的概念和作用举行了简单表明,展示了预处理的过程,并对预处理天生的hello.i文本举行了分析。
第3章 编译

3.1 编译的概念与作用


概念:编译器(ccl)通过将C语言代码转换为一条条汇编指令(将高级语言转换为面向呆板的底层指令),进而将文本文件hello.i翻译成文本文件hello.s。
作用:
(1)转换为汇编语言,使得步伐的逻辑结构更靠近底层硬件的指令集。
(2)进步可读性:汇编语言利用了类似于天然语言的符号和指令,相对于呆板语言更轻易明白和阅读,。
(3)过渡:是一个中心步调,它将被进一步汇编成目标呆板语言或二进制代码,为步伐的执行奠基底子。
3.2 在Ubuntu下编译的命令

利用gcc -S hello.i -o hello.s举行编译,其中-S选项指定 GCC 将源文件编译成汇编语言而不举行后续的汇编和链接。
利用ls命令列出文件,可见天生了预处理后的文件hello.s。

                    图3-1 编译的过程
3.3 Hello的编译效果解析

3.3.1数据处理的分析
(1)常量
与argc举行比较的常量5被作为指令的一部分,存储在了代码区

         图3-2 常量5
main函数中出现的两个字符串即为代码中的两处常量,被存放在main函数开始前的声明片段.LC1和.LC0,属于数据区。

                                   图3-3常量字符串
(2)变量
控制循环的变量i被存储在栈中(%rbp)-4的位置。

               图3-4 变量i

根据在源步伐中与5的比较条件语句,我们可以发现argc首先被存放在寄存器edi中,然后被存放在-20(%rbp)的位置。

                        图3-5 argc与5作比较的C代码

                         图3-6 argc与5作比较的汇编代码
3.3.2赋值
由C代码可知,变量i在创建时并没有举行初始化赋值,直到进入for循环才对i赋值为0,赋值过程如图所示。

                       图3-7 变量i赋值的C代码


                   图3-8 变量i赋值的汇编代码
3.3.3类型转换
表达式atoi(atgv[3])利用了显示的类型转换操纵,将字符串类型的数据转换成整数类型作为sleep函数的输入。

                 图3-9 类型转换

3.3.4算术操纵
由图3-7可见,每次循环,i都会举行+1的操纵,由3.3.1可知变量i被存储在栈中(%rbp)-4的位置,因此下面的一行汇编代码就是i++的汇编实现。


图3-10 变量i自增
3.3.5逻辑/位操纵
Hello步伐中未出现。
3.3.6控制转移
将比较效果存储在相应标记位寄存器中,依据标记位决定是否跳转到目标位置,以实现步伐控制的转移。
对于源代码中的if(argc!=5)语句,通过cmpl指令实现argc和常数5的比较,联合je指令实现条件判定与跳转,若argc为5则跳转至L2。
            

                                         图3-11  if语句的汇编代码
对于源代码中的for(i=0;i<10;i++)语句,通过cmpl指令实现变量i与常数9的比较(小于10,即小于等于9),联合jle实现对循环次数的控制,若i<=9则进入循环L4。

图3-12  for语句的汇编代码
3.3.7数组
在main函数中通过调用int main(int argc,char *argv[])传入数组argv[],ChatGPT
在汇编语言中,对数组元素的访问通常通过计算基址指针和偏移量来实现,在hello中,通过计算偏移单位8的个数来实现相应元素的访问。比方汇编指令通过-20(%rbp)和-32(%rbp)来访问argv中的两个元素。


图3-13 对数组argv的访问
3.3.8函数操纵
(1)调用printf()函数
将 %rax 寄存器的值移动到 %rsi 寄存器中,作为 printf 函数的第二个参数,即格式化字符串的地点。字符串 .LC1 的地点加被骗前指令位置偏移的效果存储到 %rdi 寄存器中,作为 printf 函数的第一个参数,即要打印的字符串的地点。将立即数 0存到 %eax 寄存器中,作为 printf 函数的返回值。
通过call指令调用 printf 函数,实现参数通报、生存返回地点、入栈、生存返回值、出栈、返回控制权等一系列过程。

                                    图3-14调用printf()函数
(2)调用exit()函数
  将立即数 1 移动到 %edi 寄存器中,作为 exit 函数的参数,用于指定步伐退出的状态码。通常情况下,状态码 0 表示正常退出,而非零状态码表示异常退出。
通过call指令调用 exit 函数,终止步伐的执行并返回给操纵系统。

           图3-15调用exit()函数
(3)调用getchar()函数
通过过程链接表举行getchar()函数的调用。

                         图3-16调用getchar()函数
(4)调用sleep()函数和atoi()函数
将 %rax 寄存器中的值移动到 %rdi 寄存器中,然后调用 atoi 函数,将 %rdi 寄存器中的值作为参数通报给该函数。将atoi函数的返回值作为调用sleep()函数的参数。

                                    图3-17用sleep()函数和atoi()函数
3.4 本章小结

本章对编译的概念和作用举行了表明,展示了编译的过程,并对编译天生的hello.s文本举行分析,了解了C语言中变量、数组、运算、赋值、控制转移、函数调用、类型转换等在汇编代码的实现方法。
第4章 汇编

4.1 汇编的概念与作用

概念:将汇编语言代码转换为呆板语言的过程。在这个过程中,汇编代码将进一步转换成呆板指令,产生一个二进制目标文件,实现从汇编到呆板语言的变化,天生可重定位目标文件。
作用:将汇编代码转换成计算性能够识别并执行的呆板语言。
4.2 在Ubuntu下汇编的命令

    利用gcc -m64 -no-pie -fno-PIC -c -o hello.o hello.s,其中-m64 选项表示天生 64 位目标文件, -no-pie 选项表示禁用可执行文件的位置无关性。

利用ls命令列出文件,可见天生了汇编后的文件hello.o。


                                                 图4-1 汇编过程
4.3 可重定位目标elf格式

通过readelf -a hello.o > hello_o.elf天生hello.o的ELF格式文件。

                                                 图4-2 天生hello.o的ELF格式文件

分析hello.o的ELF格式如图所示

            图4-3 ELF格式
(1)ELF头
ELF头是 ELF 文件的起始部分,包含了整个文件的基本信息,如文件类型、呆板架构、入口点地点等,还形貌了 ELF 文件的整体结构和结构,是 ELF 文件的入口点。


                            图4-4  ELF头信息
‘                  ’
(2)节头
形貌 ELF 文件中各个节的信息,包括节的名称、类型、大小、偏移量等,如图所示:

                                          图4-5  节头信息
(3)步伐头
步伐头表形貌步伐在内存中的结构和加载方式,包括各个段在内存中的起始地点、大小和属性等信息,通常只在可执行文件和共享库中存在。

                                          图4-6  步伐头信息
(4)重定位节
该重定位节包含两个部分:.rela.text和.rela.eh_frame,其中.rela.text节包含.text节中的位置的列表,含有该.text中所需要举行重定位操纵的信息,在举行链接时,提供给链接器,方便链接器将目标文件与别的文件链接起来。
具体:
(1)偏移量栏中标记了需要重定位的位置在.txt中的偏移量;
(2)信息栏中,最左侧的4位是省略前四位的高四字节,用以生存所调用的函数的符号表索引,右侧的8位为信息的低四字节,界说了重定位的方式type;
(3)最右侧的加数用于对被修改引用的值作偏移调整。

                                                 图4-7  重定位节信息
(5)符号表
符号表是一个记录步伐中符号信息的紧张数据结构,这些符号包括函数、变量、类型等的名称、地点、大小以及其他属性。它由汇编器构造,在编译器将源代码编译成汇编语言 .s 文件时输出。符号表的存在使得链接器能够准确地解析和处理步伐中的符号引用,从而正确地组合各个模块,并天生最终的可执行文件或共享库。


                                                 图4-8  符号表信息
4.4 Hello.o的效果解析

通过objdump -d -r hello.o得到hello.o的反汇编效果,如图所示

     图4-9  hello.o的反汇编代码
 分析hello.o的反汇编, 其与汇编语言的不同点有:
(1)汇编代码中,数值大都与C代码中一样利用十进制,反汇编代码中数字的表示都为十六进制;
(2)代码中,函数调用的具体目标地是用函数名标识的,而在反汇编代码中,是该条命令的下一条命令的地点;
(3)控制转移指令不再利用段名称(如L2)举行跳转,而是跳转到假造地点(如main+0x80)。
4.5 本章小结

本章对汇编的概念和作用举行了表明,通过汇编天生可重定位目标文件hello.o,并分析了ELF格式的内容,最后利用objdump天生了反汇编文件hello.asm,将其内容与汇编代码举行比较,总结出了二者的特点和区别。
第5章 链接

5.1 链接的概念与作用

概念:毗连器将多个目标文件链接为一个可执行步伐或共享库文件的过程,此时,这个可执行步伐才真正能被加载到内存中运行。

作用:
(1)模块化: 步伐可以编写为一个较小的源文件的集合,而不是一个整体巨大的一团,将目标文件hello.o及其他多少目标文件举行组合,天生最终的可执行文件,链接有助于步伐的模块化开辟。
(2)节约空间资源:链接器合并相同的代码和数据,减少重复代码和数据,减小最终可执行文件的大小,进步可执行文件的运行服从。
(3)节约时间:分开编译,若修改其中一个源文件,则只需要重新编译修改的文件,不需要修改其他文件。
5.2 在Ubuntu下链接的命令

利用ld命令对hello.o和其他目标文件举行链接,天生可执行步伐hello,具体命令为: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-1 链接过程
5.3 可执行目标文件hello的格式

天生ELF文件

                                           图5-2天生elf文件
ELF格式

            图5-3 ELF格式
(1)ELF头
ELF头是 ELF 文件的起始部分,包含了整个文件的基本信息,如文件类型、呆板架构、入口点地点等,还形貌了 ELF 文件的整体结构和结构,是 ELF 文件的入口点。


                           图5-4  ELF头信息
(2)节头
节头数目发生变革:由于 hello 文件需要包含可执行代码和数据,以是在其 ELF 头中会有更多的节头信息,而 hello.o 文件则只需要包含与目标文件干系的节头信息。

                                         图5-5  节头信息
(3)步伐头
步伐头表形貌步伐在内存中的结构和加载方式,包括各个段在内存中的起始地点、大小和属性等信息,通常只在可执行文件和共享库中存在。


图5-6  步伐头信息
(4)重定位节
已经履历了链接过程,不再是引用的外部符号,而是需要动态链接的函数。

                     图5-7  重定位节信息
(5)符号表
符号表是一个记录步伐中符号信息的紧张数据结构,这些符号包括函数、变量、类型等的名称、地点、大小以及其他属性。

                                                图5-8  符号表信息
5.4 hello的假造地点空间

利用edb加载hello,检察本历程的假造地点空间各段信息。Data Dump地域显示了假造地点空间的信息,可以看到hello步伐从假造空间0x401000载入,检察Symbols发现是.init的地点,与5.3中节头部表中的地点一致。


                         图5-9  hello的假造地点空间

5.5 链接的重定位过程分析

objdump -d -r hello

                    图5-10  hello的反汇编代码

不同点:
(1)main 函数以及其他语句的地点都被更换为具体的假造地点。
(2)目标文件中的跳转指令(如 jump 指令)的相对地点被更换为具体的地点。
(3)call 指令背面的内容被更换为具体的地点。
重定位过程:链接器的重定位即把每个符号界说与假造地点关联,将全部对符号的应用修改为新的假造内存地点。
链接器首先扫描目标文件,将代码中的符号引用与符号界说关联起来,并确定各个代码和数据节的大小。然后,它将每个符号界说与内存中的具体位置关联,并修改全部对这些符号的引用,使得它们指向正确的内存位置。通过这一过程,链接器将全部目标文件中的代码和数据毗连在一起,天生一个完整的可执行步伐,其中全部符号引用都被正确地解析和定位,使步伐能够在内存中正确执行。
5.6 hello的执行流程

利用edb执行hello,调用与跳转的各个子步伐名或步伐地点:
<_init>
<.plt>
<puts@plt>
<printf@plt>
<getchar@plt>
<atoi@plt>
<exit@plt>
<sleep@plt>
<_start>
<_dl_relocate_static_pie>
<main>
<_libc_scu_init>
<_libc_csu_fini>
<_fini>

                      图5-11 利用edb追踪hello流程
5.7 Hello的动态链接分析

在举行动态链接时,共享库中的代码和数据并未直接合并到可执行文件 hello 中。相反,动态链接器在加载 hello 文件时,对共享目标文件中干系模块内的代码和数据举行重定位。同时,动态链接器会加载共享库,并将其合并到 hello 文件中,天生完全链接的可执行目标文件。这一过程使得步伐能够在运行时动态地获取共享库中的函数和数据,实现了更灵活、更高效的代码共享和重用。
dl_init前:404008和404010处为空

                                  图5-12  dl_init前


动态链接接纳耽误加载的方式,只有在需要调用函数时才举行符号映射。系统利用偏移量表(GOT)和过程链接表(PLT)来实现动态链接。GOT 中存储函数的目标地点,并为每个全局函数创建副本函数,而这些副本函数位于 PLT 中。每次函数调用时,步伐先跳转到 PLT 中的副本函数,然后再由副本函数跳转到实际的函数目标地点,实现了耽误加载和符号映射。

dl_init后:加载时动态毗连器重定位这两个条目,写入了正确的地点。

   图5-13  dl_init后窗体顶端
   
窗体底端

  
5.8 本章小结

本章对链接的概念和作用举行了表明,展示了链接的过程,分析了可执行hello步伐的反汇编代码,检察了其ELF格式内容;比较了反汇编代码与hello.o反汇编的不同,并通过edb运行hello步伐,观察了动态链接器对地点的加载过程。
第6章 hello历程管理

6.1 历程的概念与作用

概念:历程指正在运行的步伐在操纵系统中的实例。
作用:
(1)创建了步伐运行的独特上下文,提供了两个抽象:
a.提供独立的逻辑控制流,好像我们的步伐独占地利用处理器;
b.提供一个私有的地点空间,好像我们的步伐独占地利用内存系统,
(2)历程的抽象概念,有效地防止了应用步伐对硬件的滥用,并为应用步伐提供了一致简单的接口来控制各种底层硬件设备,使得应用步伐开辟者无需关心底层硬件的复杂性和差异性。
6.2 简述壳Shell-bash的作用与处理流程

作用:shell是系统的用户界面,提供了一个用户与内核举行交互的接口,它接受用户的命令,并将命令送到内核执行,通过这个接口用户可以执行步伐。
处理流程:
(1)从用户键盘输入获取命令。
(2)对输入的命令举行格式验证,并调整参数格式,以符合执行 execve() 系统调用的要求。
(3)利用 fork() 创建子历程,并在主历程中等待子历程执行完毕。
(4)当子历程开始执行时,利用 execve() 函数在文件系统中查找并加载命令对应的可执行文件,并在内存中执行该命令。
(5)假如命令行末端包含背景命令符号 &,则主历程将立即返回,并显示提示符,准备接受下一条命令,而无需等待子历程执行完毕。
6.3 Hello的fork历程创建过程

    运行 Hello 步伐时,操纵系统创建一个历程,执行 main 函数中的代码。调用 fork() 函数创建子历程,子历程拷贝父历程的地点空间,但有独立的地点空间。子历程从函数返回并返回值为 0,父历程返回子历程的历程 ID。子历程执行与父历程相同的代码,父历程通过子历程的历程 ID 举行识别。


在hello所处的目录下输入./hello 2022112503  孙柯柯 15153037505 0(学号,姓名,手机号,秒数)并回车运行,shell就会对我们输入的命令行举行解析,并通过fork函数为hello步伐创建一个新的子历程。新创建的子历程得到与父历程用户级假造地点空间相同的,但是独立的一个副本,子历程与父历程直接拥有不同的PID。




                        图6-1 创建历程
6.4 Hello的execve过程

在调用 fork() 之后,新创建的子历程会调用 execve() 函数,在当前子历程的上下文中加载 hello 步伐,并立即开始运行,接下来删除已存在的用户地域并映射私有区和共享区,然后跳转到hello的入口点,将控制权转移到子历程。
execve() 函数需要三个参数:步伐路径、命令行参数数组和情况变量数组。在 Hello 步伐中调用 execve() 函数时,通报了相应参数。与 fork() 调用不同,execve() 调用只执行一次且永不返回。execve() 函数调用将驻留在内存中的操纵系统代码称为启动加载器,该加载器负责执行步伐。加载器将可执行目标文件中的代码和数据从磁盘复制到内存中,并通过跳转到步伐的第一条指令或入口点来运行该步伐。
调用 execve() 函数后,操纵系统会将当前历程的映像更换为指定步伐的映像,并开始执行该步伐的代码。因此,Hello 步伐的代码不再执行,而是被更换为新步伐的代码执行。
6.5 Hello的历程执行


在Hello步伐的执行过程中,涉及到许多操纵系统概念,如历程上下文信息、历程时间片、历程调度以及用户态到焦点态的转换。
(1) 历程上下文信息包括历程的状态信息,如步伐计数器、寄存器、内存管理信息等。在切换历程时,操纵系统需要生存当前历程的上下文信息,并加载下一个历程的上下文信息,这就是历程切换。
(2) 历程时间片是操纵系统为每个历程分配的可执行时间段。当历程的时间片用完时,操纵系统会克制执行,并将CPU时间分配给下一个等待的历程,以确保系统的服从和稳定性。
(3) 历程调度是操纵系统的一个紧张组件,负责确定哪个历程应该罗致CPU时间片。常见的调度算法包括轮询调度、优先级调度和时间片轮换调度。
(4) 从用户状态到焦点状态的转换是指历程在操纵系统中运行时从用户状态切换到焦点状态。在用户模式下,历程只能访问本身的用户空间;在核思维中,流程可以访问全部系统资源。当历程需要访问内核资源时,需要通过系统调用将其从用户态转换为内核态。
6.6 hello的异常与信号处理

hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
异常种类:停止、陷阱、故障、终止
信号种类:停止和终止信号。
处理:停止信号SIGSTP会导致历程暂停直到SIGCONT信号使其继续运行;SIGINT信号则会终止步伐。
当秒数为0时,历程结束太快,来不及从键盘输入,以是将秒数变为5。
不停乱按:输入存储到缓冲区,步伐正常运行。

                     图6-2 不停乱按

Ctrl-C:步伐收到SIGINT信号终止。

                            图6-3 ctrl-c
Ctrl-Z:步伐收到SIGSTP信号暂停

                             图6-4 ctrl-z
ps命令:显示了暂停中的hello历程的信息。

                          图6-5 ps
pstree命令:显示历程树。

                      

                                图6-6 pstree

jobs命令:显示hello作业信息。

                                    图6-7 jobs
fg命令:恢复前台运行,步伐顺利运行退出。

                                图6-8 fg
Ctrl-Z暂停后利用kill命令杀死历程,发送SIGKILL信号:

                              图6-9 kill
6.7本章小结

本章对历程的概念和作用举行了表明,展示了历程执行的步调,分析了历程执行的过程,fork和execve过程,以及信号和异常的处理。
第7章 hello的存储管理

7.1 hello的存储器地点空间

(1)逻辑地点:在Hello步伐中,逻辑地点是指步伐中利用的相对于段基地点的偏移地点。比方,当步伐需要访问变量或执行代码时,它们所利用的地点都是相对于段基地点的偏移量。
(2)线性地点:逻辑地点经过段基地点的加法运算得到的效果。在地点转换过程中,逻辑地点首先被转换为线性地点,线性地点包含了逻辑地点的偏移量以及段基地点,它是逻辑地点和物理地点之间的中心层。
(3)假造地点:步伐中利用的地点,与实际物理内存无关。在Hello步伐执行时,假造地点提供了一种抽象的地点空间,使得步伐可以独立于实际物理内存的位置举行编写和执行。
(4)物理地点:实际存储在主存上的地点。在Hello步伐执行时,可以通过物理地点可以直接访问主存中的数据。

图7-1 地点空间

7.2 Intel逻辑地点到线性地点的变换-段式管理

地点的构成包括段选择符和段内偏移量两部分。段选择符的长度为16位,它确定了起始位置的线性地点。通过将段选择符与段内偏移量相加,可以得到完整的线性地点,这个线性地点指向了在内存中的具体位置。

图7-2 段式管理
7.3 Hello的线性地点到物理地点的变换-页式管理

在Hello步伐中,线性地点到物理地点的变换通过页式管理来实现。分为静态和动态两种,将假造空间分为多少个长度相等的页,地点分成两部分,页号和页内偏移量,线性地点的高位部分是页号,它用于索引页表,线性地点的低位部分是页内偏移量,它表示了在页内的偏移量。然后创建页表来管理,通过查找页表,可以得到物理地点,通过物理地点可以直接访问内存中的数据。

                图7-3 页式管理

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

当处理Hello步伐中的地点时,系统首先查抄TLB是否掷中。假如TLB掷中,系统可以直接从TLB中获取相应的页表项,并从中获取物理地点,然后访问相应的数据。这样可以加速地点转换过程,进步访存服从。

                       图7-4  TLB掷中
假如TLB未掷中,即未在TLB中找到相应的页表项,则系统会触发缺页异常。此时,操纵系统的缺页处理步伐会被调用。缺页处理步伐会确定哪一页需要被换出,以便为新的请求页面腾出空间。一旦页面被换出,系统会加载新的请求页面,并更新页表。然后,原来的历程会被恢复,并重新执行之前的指令。

                        图7-5  TLB不掷中
通过利用四级页表的机制,系统可以将地点转换的过程分成多个条理。每个条理的页表只需存储部分地点的映射关系,而不是全部的地点映射关系。这样可以节流内存空间,并减少了访问页表的次数,从而进步了地点转换的服从。

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

CPU天生假造地点(VA),将其传送给内存管理单位(MMU)。MMU利用假造地点的假造页号(VPN)的高位作为索引,向转换后备缓冲器(TLB)中探求匹配的条目。假如TLB中找到了匹配的条目(TLB hit),则MMU可以直接从TLB中获取对应的物理地点(PA)。
假如TLB中没有找到匹配的条目(TLB miss),则MMU会查询页表。控制寄存器CR3确定了第一级页表的起始地点。VPN的第一部分(VPN1)确定了在第一级页表中的偏移量,从而找到第二级页表的起始地点。接着,VPN的第二部分(VPN2)确定了在第二级页表中的偏移量,以图片7-6中的一级cache为例,以此类推,直到找到第四级页表,从中获取物理页号(PPN)。然后,MMU将假造页偏移(VPO)与找到的物理页号(PPN)组合,得到物理地点(PA),并将其添加到物理地点总线(PLT)上,从而完成地点转换。

                 图7-6  一级cache
7.6 hello历程fork时的内存映射

fork()系统调用在子历程中返回0,在父历程中返回子历程的历程ID。当子历程被创建时,其历程地点空间会被操纵系统中的MMU重新映射,以反映新的历程地点空间,即:

(1)创建新历程时,当前历程的mm_struct、vm_area_struct以及页表都会被复制。
(2)每个页面在两个历程中都被标记为只读状态。
(3)每个地域结构也在两个历程中被标记为私有的写时复制。
(4)新历程返回后,它会拥有与调用fork的历程相同的假造内存。
(5)后续的写操纵会通过写时复制机制创建新页面,这保证了新历程和父历程之间的内存共享只在它们之间没有写操纵时才会见效。

7.7 hello历程execve时的内存映射

当hello历程调用execve函数时,它会清空本身的假造地点空间,并载入可执行文件的代码和数据段,重新映射新的假造地点到物理内存中。具体过程是:
(1)内核读取可执行文件的步伐头表,并解析出各个段的信息。
(2)分配新的页表,并创建新的假造地点空间。
(3)从可执行文件中读取代码段、数据段等信息,并将它们映射到新的假造地点空间。
(4)设置步伐的入口地点为代码段的起始地点。
在这个过程中,hello历程的假造地点空间会包括代码段、数据段、堆和栈等部分,它们各自有不同的大小和起始地点。内核会根据物理内存的情况选择合适的物理页面来存储这些段,并利用CPU的TLB缓存加速假造地点到物理地点的转  图7-7   内存映射

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

缺页故障:指当CPU试图访问假造地点空间中的某一页,而该页尚未被加载到物理内存时发生的情况。
缺页停止处理:
(1)暂停当前CPU的执行,将控制权转移给操纵系统内核。
(2)操纵系统内核会根据缺页停止的信息,确定需要将哪一页从磁盘加载到内存中。
(2)若物理内存有空余,直接将页加载到空余处。
(3)若物理内存无空余,由内核中的缺页处理步伐选择一个牺牲页,假如这个牺牲页被修改过,那么就将它交换出去,换入新的页并更新页表。
(4) 一旦所需的页面被加载到内存中,操纵系统会更新页表,将对应的页表项设置为有效,以表示页面已经被加载到物理内存中。
(5)CPU重新启动引起缺页的指令,这条指令再次发送VA到MMU,这次访问即会掷中。

                   图7-8   缺页故障
7.9动态存储分配管理

动态存储分配管理是操纵系统的焦点功能,它负责有效管理历程在运行时所需的内存空间。操纵系统通过维护一个名为堆的假造内存地域来实现这一目标。堆由一系列不同大小的块组成,每个块都可能处于"已分配"或"空闲"状态。步伐员可以通过malloc函数申请内存空间,并通过free函数释放内存空间。而栈是由系统主动管理的内存空间,用于存储函数的参数、局部变量等。栈接纳"先进后出"的方式举行分配,系统为每个函数调用分配一段内存,在函数执行完毕后主动释放该内存空间。步伐员在举行动态存储分配时需要细致管理内存的申请和释放。

图7-9   动态存储分配管理

7.10本章小结

本章对存储器地点空间的概念举行了表明,表明了段式管理和页式管理的含义,具体阐明了TLB与四级页表支持下的VA到PA的变换和三级Cache支持下的物理内存访问过程,展示了hello历程fork和execve时的内存映射,并对缺页处理和动态存储分配管理举行了分析。
第8章 hello的IO管理

8.1 Linux的IO设备管理方法

设备的模型化:文件。在Linux系统中,每个设备都会被视为一个文件,对设备的操纵都通过打开、读、写、关闭文件来完成,每个打开的文件、设备或套接字都与一个唯一的文件形貌符干系联。应用步伐可以利用文件形貌符举行IO操纵,包括读取、写入和控制设备。
设备管理:unix io接口。提供统一的Unix I/O接口来完成输入输出的操纵,进而对IO设备举行管理。Linux还提供了异步IO接口,允许应用步伐在发起IO操纵后继续执行其他使命,而无需等待IO操纵完成。
8.2 简述Unix IO接口及其函数

Unix系统提供了一系列I/O接口,可以执行诸如打开文件、关闭文件、移动位置、读取和写入等多种基本操纵。以下是一些常用的函数及其功能:

(1)open():用于打开文件或设备,并返回一个文件形貌符。原型为int open(const char *pathname, int flags)。

(2)close():关闭文件或设备,函数原型为int close(int fd),其中fd为文件形貌符。

(3)read():从指定文件的指定位置读取指定字节数到缓冲区中,并返回乐成读取的字节数。假如出错,返回-1;假如到达文件结尾,返回0。

(4)write():将缓冲区中的指定字节数写入文件的当前位置,返回实际写入的字节数。假如出错,返回-1。

(5)lseek():用于设置文件或设备的读写位置,返回新的文件位置。函数原型为off_t lseek(int fd, off_t offset, int whence)。

(6)ioctl():用于对文件或设备举行控制操纵,比方设置设备参数或获取设备状态。此函数可以用于特定设备操纵,提供了更多的灵活性。

8.3 printf的实现分析

https://www.cnblogs.com/pianist/p/3315801.html
int printf(const char *fmt, ...)
{
int i;
char buf[256];
     va_list arg = (va_list)((char*)(&fmt) + 4);
     i = vsprintf(buf, fmt, arg);
     write(buf, i);
     return i;
    }
参数…的写法实现了不确定个数参数的通报。
printf函数解析格式化字符串并将参数转换为字符串,天生输出字符串。输出字符串暂存在内部缓冲区,满了或遇到换行符时将内容输出到IO设备,涉及系统的IO接口,如write函数或系统调用。对于显示设备,还需经过字符显示驱动处理,确保字符串正确显示在屏幕上。
int vsprintf(char *buf, const char *fmt, va_list args)
{
char* p;
char tmp[256];
va_list p_next_arg = args;
for (p=buf;*fmt;fmt++) {
if (*fmt != '%') {
*p++ = *fmt;
continue;
}
fmt++;
switch (*fmt) {
case 'x':
itoa(tmp, *((int*)p_next_arg));
strcpy(p, tmp);
p_next_arg += 4;
p += strlen(tmp);
break;
case 's':
break;
default:
break;
}
}
return (p - buf);
}
信息从vsprintf天生,通过write系统函数或陷阱-系统调用通报。字符显示驱动步伐负责处理从ASCII字符到字模库再到显示显存中的信息,最终由显示芯片按革新频率逐行读取显存,并通过信号线将每个点的RGB分量传输到液晶显示器。
8.4 getchar的实现分析

int getchar(void)

{

static char buf[BUFSIZ];

static char *bb = buf;

static int n = 0;

if(n == 0)

{

n = read(0, buf, BUFSIZ);

bb = buf;

}

    return(--n >= 0)?(unsigned char) *bb++ : EOF;

}
   
异步异常-键盘停止的处理:键盘停止处理子步伐。接受按键扫描码转成ascii码,生存到系统的键盘缓冲区。
getchar函数通过read系统调用从标准输入读取字符,键盘按下时,系统停止处理步伐将扫描码转换为字符编码,并写入输入缓冲区,getchar函数则在此时见效,只有检测到回车符时,才会整体读取输入缓冲区的内容。
8.5本章小结

本章阐释了Linux的IO设备管理方法,对Unix IO接口及其函数举行了简要介绍,然后分析了函数printf()和函数getchar()的实现过程。

结论

hello所履历的过程:
1.编写C语言源代码:步伐员编写hello的源代码,包括所需的功能和逻辑。
2.预处理:对源代码举行预处理,包括展开宏、包含头文件等操纵,天生预处理后的文件。
3.编译:将预处理后的文件编译成汇编代码,即将C语言代码转换为汇编代码。
4.汇编:将汇编代码转换为呆板语言的目标文件,即二进制文件,包含了呆板可读的指令。
5.链接:将多个目标文件链接为一个可执行文件,解析符号并将它们关联起来,天生最终的可执行步伐。
6.创建历程:shell通过创建历程并加载运行hello可执行步伐,将hello步伐加载到内存中准备执行。
7.创建假造内存:为历程分配内存资源,包括代码段、数据段、堆、栈等。
8.CPU执行步伐指令:CPU根据步伐指令从内存中读取指令并执行,执行步伐的逻辑和功能。
9.异常与信号处理:步伐执行过程中,可能会发生异常或罗致到信号,操纵系统会举行相应的处理,包括IO功能实现等。
10.步伐结束:步伐执行完成后,操纵系统接纳历程所占用的资源,包括内存等,释放系统资源。
感悟:
小小的hello步伐固然简单,真正要实现起来,也要经过许多步调,这让我对计算机步伐的运行多了许多敬畏之心。同时还让我意识到,事物的外貌看起来简单,但其背后可能隐藏着繁杂的细节和复杂的实现过程。以是在面对问题时,需要深入了解其背后的原理和机制,以便更好地明白息争决问题。这警示着我要保持谦虚和开放的心态,乐意接受并学习新的知识和技能,以不断提升本身的能力和程度,进而才华了解这个复杂又精彩的世界。
附件

hello.i:预处理后的步伐代码文件;
hello.s:编译后的汇编代码文件;
hello.o:汇编后的步伐目标文件;
hello.elf:hello.o的elf输出效果;
hello.asm:hello.o的反汇编;
hello:可执行步伐;
hello2.elf:hello的elf输出效果;
hello2.asm:hello的反汇编;
参考文献

[1]  https://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html
[2]  https://zhuanlan.zhihu.com/p/463100471


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

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

渣渣兔

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表