摘 要
本论文围绕hello步伐,体系分析了C语言步伐从源代码到可执行进程的全生命周期。详细论述了预处理处罚、编译、汇编、链接(P2P过程)及进程管理、存储管理(020过程)的核心机制。在Ubuntu环境下,利用GCC工具链生成预处理处罚文件、汇编代码、可重定位目标文件和可执行文件,结合readelf、objdump等工具解析ELF格式与机器指令。重点探讨了动态链接、假造地址空间映射、页式存储管理及信号处理处罚机制,揭示了进程通过fork、execve加载执行的内涵原理。通过调试工具验证了异常处理处罚、TLB与Cache对内存访问的优化作用,完备出现了步伐从静态代码到动态进程的转化过程及其盘算机体系底层支持。
关键词:盘算机体系;P2P过程;020过程
(摘要0分,缺失-1分,根据内容出色称都酌情加分0-1分)
第1章 概述
1.1 Hello简介
P2P(From Program to Process)过程,指步伐从GCC编译器的驱动步伐读取并翻译为可执行目标文件hello.o;而后,操纵体系外壳shell利用函数fork为hello创建进程process。详细包罗以下五个步骤:
- 预处理处罚(Preprocessing)
预处理处罚器(cpp)对hello.c举行宏展开、头文件包罗、注释删除等操纵,生成hello.i文本文件。
- 编译(Compilation)
编译器(如cc1)将hello.i翻译为汇编代码文件hello.s,完成语法分析、语义优化,将高级语言转换为机器相关的低级指令。
- 汇编(Assembly)
汇编器(as)将hello.s转换为机器码,生成可重定位目标文件hello.o,包罗二进制指令和未解析的符号引用。
- 链接(Linking)
链接器(ld)合并hello.o与标准库(如libc.so),解析外部符号地址,生成可执行文件hello,具备完备的假造地址空间布局。
- 进程创建(Process Creation)Shell通过fork()创建子进程,再调用execve()加载hello,将其代码段、数据段映射到进程假造地址空间,完成从静态步伐到动态进程的变化。
020(From Zero-0 to Zero-0) 指步伐从初始未被加载(零状态)到执行结束后被体系接纳资源并完全制止(回归零状态)的生命周期,即从无到有再到无的完备过程。主要包罗以下三个过程:
- 初始状态(Zero-0)
步伐未执行时,内存中无相关数据,进程表项和资源均未分配
- 加载与执行
- execve()调用加载器,为hello分配假造内存页,映射代码、数据段至物理内存,初始化堆栈段为0值。
- CPU通过流水线执行指令:取指→译码→执行,利用TLB和三级缓存(L1/L2/L3)加速内存访问。
- I/O管理(如printf)通过体系调用将输出传递至终端装备。
- 制止与接纳(Zero-0)
- 步伐执行结束后,父进程(Shell)通过waitpid()接纳子进程,释放内存、文件描述符等资源。
- 内核扫除进程控制块(PCB)、页表项等数据结构,hello的全部痕迹从体系中消散。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
硬件化境:Intel Core i9-13980HX
软件环境:Windows11+ Ubuntu 24.04.2
开发与调试工具:gdb
1.3 中心结果
列出你为编写本论文,生成的中心结果文件的名字,文件的作用等。
文件名
| 作用
| hello.i
| 预处理处罚后文件
| hello.s
| 汇编文件
| hello.o
| 可重定位的可执行文件
| hello
| 链接后的可执行文件
| hello_elf.txt
| hello.o readelf结果
| hello_elf2.txt
| hello readelf结果
| hello_obj.txt
| hello.o反汇编结果
| hello_obj2.txt
| hello 反汇编结果
|
1.4 本章小结
本章对hello步伐的P2P过程以及020过程举行总体概述,说明白本文的开发环境与调试工具以及生成的中心结果。
(第1章0.5分)
第2章 预处理处罚
2.1 预处理处罚的概念与作用
步伐预处理处罚是指在源代码被正式编译前,由预处理处罚器对代码举行文本处理处罚的阶段。它主要处理处罚以 # 开头的预处理处罚指令(如宏定义、文件包罗、条件编译等),通过宏更换、文件合并、条件筛选等操纵生成修改后的源代码,供后续编译使用。预处理处罚不涉及语法分析,仅对文本举行直接操纵,属于编译过程的“预备工作”。
- 预处理处罚的作用
- 代码复用与模块化
通过 #include 指令将头文件内容插入当前文件,淘汰重复代码。
- 提高可移植性
使用条件编译(如 #ifdef)可根据差别平台或环境选择性地编译代码,增强跨平台兼容性。
- 简化代码维护
宏定义(#define)允许用常量或代码片断更换复杂表达式,修改时只需调解宏定义,无需逐一修改代码。
- 优化编译过程
预处理处罚会删除注释和冗余空白,淘汰编译时的处理处罚负担。
2.2在Ubuntu下预处理处罚的命令
Linux下使用GCC编译器举行预处理处罚的指令为:
gcc -E hello.c -o hello.i
| 图2.1 在Ubuntu下对hello.c举行预处理处罚截图
| 2.3 Hello的预处理处罚结果解析
起始的代码段为头文件展开,全部 #include 被更换为对应文件的内容。背面是宏和范例定义以及声明体系调用函数,如sleep和getchar。用户代码被保存在最后。
2.4 本章小结
本章讨论了预处理处罚的概念与作用,并对hello.c文件举行预处理处罚,最后扼要解析预处理处罚后的hello.i文件。
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
编译是将高级编程语言编写的源代码,通过编译器转换为盘算机可执行的机器代码或低级中心代码的过程。这一过程通常包罗词法分析、语法分析、语义分析、代码优化和目标代码生成等步骤。
编译主要有以下作用
- 跨平台兼容性:通过编译生成差别平台(如Windows、Linux)的机器码,使步伐可移植。
- 性能优化:编译器会优化代码(如删除冗余盘算),提升执行服从。
- 错误检查:编译时能检测语法、范例等错误,提前发现埋伏问题。
- 代码保护:生成的二进制文件难以直接逆向,保护知识产权。
- 标准化执行:编译后的步伐独立于源代码,确保运行环境一致性。
3.2 在Ubuntu下编译的命令
在Ubuntu体系下执行编译的命令为:
gcc- S hello.i -o hello.s
| 图3.1 在Ubuntu下对hello.i举行编译截图
| 3.3 Hello的编译结果解析
3.3.1常量
整形常量在编译后的文件中以立即数的形式表示,如图3.2.1.
字符串常量存储于只读数据段中,如图3.2.2所示。
3.3.2 局部变量
局部变量int i通过堆栈实现,如图3.3.1所示,源代码中的局部变量int i在编译后存入堆栈,并用帧指针寄存器%rbp+ 偏移量的形式表示。
3.3.4 if条件跳转
条件跳转通过cmpl操纵判断条件是否成立并改变条件码后调用条件跳转指令je依据条件码举行条件跳转,如图3.4.1所示.
| 图3.4.1 if条件跳转在编译后的文件的表示形式
| 3.3.5 赋值操纵
赋值操纵通过mov指令实现,如图3.5.1所示。
3.3.6 关系操纵
C文件中循环控制中判断变量i与10大小的操纵,汇编后通过cmpl指令实现,如图3.6.1所示
3.3.7 for循环
C文件中的for循环操纵汇编后通过指令cmpl比较循环控制变量和立即数10的大小并改变条件码,再通过条件跳转指令依据条件码举行跳转来实现循环控制,如图3.7.1所示。
3.3.8函数操纵
函数调用的参数传递通过调用函数前将参数存储到特定寄存器实现,比方调用printf函数前,函数的第一个参数,即printf的输出格式被储存到寄存器%rdi中,如图3.8.1所示。
函数调用通过call指令实现,如图3.8.2所示
3.3.9 算术操纵
C文件中的算术操纵i++在汇编文件中通过addl指令实现,如图3.9.1所示。
3.3.10 数组操纵
C文件中的数组argv[ ]在汇编中通过堆栈存储其首地址,再通过首地址加偏移量的方式对其个元素举行操纵,如图3.10.1所示。
3.4 本章小结
本章扼要先容了编译的概念以及意义,并对hello.c文件举行编译,最后对编译后的hello.s文件举行解析。
(第3章2分)
第4章 汇编
4.1 汇编的概念与作用
汇编,即将汇编代码转换为机器码(.o目标文件)。通过这种底层转换,汇编在体系软件、高性能盘算、安全研究等领域发挥着不可替代的作用,是毗连高级语言与机器硬件的关键桥梁。
4.2 在Ubuntu下汇编的命令
Linux下执行汇编的命令为:
gcc -c hello.s -o hello.o
4.3 可重定位目标elf格式
通过readelf -a hello.o > hello_elf.txt指令,体现hello.o文件的各种信息并保存至hello_elf.txt中。
4.3.1 ELF头(ELF header)
ELF头中包罗了描述ELF文件整体结构和属性的信息,包罗ELF标识、目标体系结构、节表偏移、步伐头表偏移等信息,如图4.2所示。
4.3.2 节头(section header)
ELF 文件中的节头是描述文件中各个节的关键元数据结构。每个节头对应一个节,记录了该节的名称、范例、地址、大小、对齐方式等属性,如图4.3所示
4.3.3 重定位节(relocation section)
重定位节记录了在链接或加载时需要修改的地址信息,这些条目告诉链接器哪些位置的符号地址需要在链接时举行调解,以便正确地指向目标地址,如图4.4所示。
4.3.4 符号表(symbol table)
符号表存储步伐中全部符号(函数、变量)的名称和地址信息,供链接器解析跨模块的引用关系,如图4.5所示。
4.4 Hello.o的结果解析
通过指令objdump -d -r hello.o > hello_obj.txt对hello.o文件举行反汇编,并将结果保存到hello_obj.txt中。
4.4.1 机器语言与汇编语言的对照分析
反汇编代码中分支转移目标地址由相对于当前函数起始地址的偏移量给出,如图4.6所示。
而.s文件中的分支转移目标地址由代码段名称给出,如图4.7所示。
反汇编中的函数调用的目标地址是一个偶然义的占位符,如图4.8所示,其真实目标地址需要通过链接时的重定位来确定。
而.s文件中的函数调用指令call背面接的是目标函数的函数名,如图4.9所示。
汇编语言中的立即数为十进制,而反汇编机器码中为十六进制,如图4.10所示。
4.5 本章小结
本章说明白汇编的寄义及作用,对hello.s文件举行汇编得到hello.o文件,并对汇编后的可执行文件举行分析。
(第4章1分)
第5章 链接
5.1 链接的概念与作用
5.1.1 链接的概念
链接是将一个或多个目标文件与所需的库组合成可执行文件的过程。在此过程中,链接器会解析目标文件中的符号引用,将差别目标文件的代码段和数据段按规则合并,并完成地址空间分配和重定位。对于静态链接,库代码会被直接复制到终极文件中;而动态链接则仅记录依靠信息,在步伐运行时由动态链接器加载共享库。
5.1.2 链接的作用
链接的核心作用是生成可直接运行的步伐,解决模块化开发中的代码整合问题。它通过合并代码、绑定符号地址,将分散编译的可重定位目标文件和体系库中的函数逻辑串联成完备的可执行文件。链接器还会优化内存布局,并生成步伐头以指导操纵体系加载文件到内存。终极,链接过程确保步伐能独立运行,全部外部函数调用和全局数据引用均指向正确的内存位置,从而将开发者编写的源码转化为盘算机可执行的指令集合。
5.2 在Ubuntu下链接的命令
Linux下的链接命令为
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 -a hello > hello_elf2.txt指令,体现hello文件的各种信息并保存至hello_elf2.txt中。
5.3.1 ELF头(ELF header)
ELF头中包罗了描述ELF文件整体结构和属性的信息,包罗ELF标识、目标体系结构、节表偏移、步伐头表偏移等信息,如图5.2所示。
4.3.2 节头(section header)
ELF 文件中的节头是描述文件中各个节的关键元数据结构。每个节头对应一个节,记录了该节的名称、范例、地址、大小、对齐方式等属性,如图5.3所示。
可以看出,链接后的可执行文件相比未链接的目标文件,其节头中新增了动态链接相关节(如 .interp 指定动态加载器、.dynsym 动态符号表、.plt 和 .got 实现延迟绑定)、运行时初始化节(如 .init 和 .fini 定义全局构造/析构函数)、去除了重定位节(如 .rela.text 已被链接器处理处罚),同时全部节的假造地址(Address 字段)被分配为详细值,且文件范例从 REL(可重定位)变为 EXEC(可执行),表明其已具备完备的加载和执行能力。链接器通过合并代码、解析外部符号、绑定动态库函数,将原始目标文件转化为可直接加载到内存并运行的独立步伐。
分析hello的ELF格式,用readelf等列出其各段的基本信息,包罗各段的起始地址,大小等信息。
5.4 hello的假造地址空间
使用gdb加载可执行文件hello,在主函数处设置断点并运行至断点处,如图5.4所示。
使用指令info proc mappings 查看假造地址空间各段信息,如图5.5所示。
下面举例对本进程的假造地址空间各段信息举行与5.3对照说明。
1 .text节
.text节对应的readelf节头信息为:
[15] .text PROGBITS 00000000004010f0 000010f0 Size: 0xd8, Flags: AX (可执行)
而对应在本进程中的假造空间段地址为0x401000-0x402000,包罗 .text 节的假造地址 0x4010f0
2 .rodata节
.rodata节对应的readelf节头信息为:
[17] .rodata PROGBITS 0000000000402000 00002000 Size: 0x48, Flags: A (只读)
而对应在本进程中的假造空间段地址为0x402000-0x403000,包罗 .rodata 节的假造地址 0x402000。
3 .data节和 .got.plt节
readelf节头信息为:
[22] .data PROGBITS 0000000000404030 00003030 # 已初始化数据
[21] .got.plt PROGBITS 0000000000403fe8 00002fe8 # 全局偏移表(动态链接)
而对应在本进程中的假造空间段地址为0x404000-0x405000,包罗 .data 和 .got.plt的假造地址。
5.5 链接的重定位过程分析
通过指令objdump -d -r hello > hello_obj2.txt对hello文件举行反汇编,并将结果保存到hello_obj2.txt中。
5.5.1 hello与hello.o的差别
特征
| hello.o(未链接)
| hello(已链接)
| 函数调用地址
| call 指令目标地址为 0x0(占位符)
| call 指令指向详细地址(如 puts@plt)
| 全局数据引用
| 使用相对偏移(如 lea 0x0(%rip),%rax),需重定位
| 直接引用 .rodata 的实际地址(如 lea 0xead(%rip),%rax)
| 重定位信息
| 存在 .rela.text 等重定位节(如 R_X86_64_PLT32)
| 无重定位节(链接器已处理处罚)
| 动态链接支持
| 无 PLT/GOT 表
| 新增 .plt、.got.plt 节,支持动态链接(如 puts@plt)
| 初始化代码
| 无 .init、.fini 节
| 包罗 _init 和 _fini 函数,处理处罚全局构造/析构
| 5.5.2 链接的过程
毗连主要包罗以下两步:
1.符号解析
符号解析是链接过程中链接器将差别模块(如目标文件、库文件)中的 符号引用(如函数名、全局变量)与其对应的 符号定义 举行匹配的过程。比方,在 hello.o 中调用 puts 函数时,目标文件仅记录了对 puts 的引用(符号未定义),链接器会遍历全部输入文件(如 libc.so)找到 puts 的实际定义,并确认其地址。此过程确保步伐中的全部符号引用(如函数调用、全局变量访问)都能正确绑定到内存中的有效位置,若找不到定义则报错(如 undefined reference)。符号解析是链接的核心步骤,解决了模块化开发中代码分散的问题。
2.重定位
重定位是链接器根据符号解析的结果,对目标文件中的 地址引用 举行修正,使其指向可执行文件或内存中的 实际运行时地址 的过程。比方,hello.o 中的 call puts 指令本来指向暂时占位地址(0x0),链接后修正为 puts@plt(位于 .plt 节),而 .plt 中的代码会通过 .got.plt 表间接跳转到动态库 libc.so 中的 puts 实现。链接器还会集并全部目标文件的代码段(.text)和数据段(.data、.rodata),重新盘算相对偏移(如 lea 0xead(%rip),%rax 中的 0xead 对应 .rodata 中的字符串地址),终极生成可直接加载到内存运行的二进制文件。重定位实现了地址空间的同一分配,是步伐从零散模块到完备可执行体的关键步骤。
5.5.3重定位过程
链接前call指令的目标地址为偶然义的占位符,毗连后为详细的假造内存地址,如图5.6所示。
5.6 hello的执行流程
通过gdb加载hello,先设置捕获全部函数的断点,再通过对每个断点附加命令使其自动打印调用信息,如图5.7所示。
结果如图5.8所示。
| 图5.8 步伐执行中的过程以及各个子步伐名或步伐地址
| 5.7 Hello的动态链接分析
分析hello步伐的动态链接项目,通过edb/gdb调试,分析在动态链接前后,这些项目标内容厘革。要截图标识说明。
5.7.1 动态毗连过程
动态链接是步伐运行时由动态链接器(如ld-linux.so)完成的,主要过程如下:
操纵体系加载可执行文件(如hello),读取其头部信息,确定依靠的共享库(如libc.so)。
动态链接器递归加载全部依靠的共享库到内存,并为它们分配地址空间。
解析可执行文件和共享库中的未定义符号(如printf),找到其在共享库中的实际地址。
修改可执行文件中的全局偏移表(GOT)和过程链接表(PLT),将符号的地址填充到GOT中。
初次调用函数(如puts)时,通过PLT跳转到动态链接器的解析函数,解析符号地址并更新GOT,后续调用直接跳转到目标地址。
5.7.2 hello动态链接前后动态链接项目标内容厘革
通过gdb加载hello步伐,并在main函数和printf函数调用前分别设置断点,如图5.9所示。
观察反汇编代码,printf函数对应GOT条目地址为0x404008,运行步伐,在第一个断点处用x指令查看printf函数对应GOT条目内容,如图5.10所示。
继续运行步伐,在第二个断点处单步运行步伐至调用printf函数后,再次用x指令查看printf函数对应GOT条目内容,如图5.11所示。
可以看到,动态链接前后printf函数对应的GOT条目发生厘革,动态链接前GOT条目指向动态链接器的解析逻辑,动态链接后更新为函数实际地址。
5.8 本章小结
本章扼要先容链接的作用与概念,对hello.o举行毗连并生成终极的链接后的可执行步伐hello,并对其举行分析。
(第5章1分)
第6章 hello进程管理
6.1 进程的概念与作用
6.1.1 进程的概念
进程是盘算机体系中步伐执行的基本单元,代表了一个正在运行的步伐的实例。它不仅包罗步伐代码和当前执行状态(如步伐计数器、寄存器值等),还涉及运行时所需的内存、文件描述符等体系资源。操纵体系通过创建和管理进程实现对多使命的支持,每个进程在独立的地址空间中运行,确保相互隔离且互不干扰。进程的动态性和独立性使得盘算性能够高效分配CPU时间片、处理处罚并发使命,并为用户提供步伐并行执行的体验。
6.1.2 进程的作用
进程提供给应用步伐的关键抽象:
一个独立的逻辑控制流,它提供一个假象,似乎我们的步伐独占地使用处理处罚器。
一个私有的地址空间,它提供一个假象似乎我们的步伐独占地使用内存体系[1]
6.2 简述壳Shell-bash的作用与处理处罚流程
6.2.1壳的作用
Shell是用户与操纵体系内核交互的核心接口,既提供命令行环境供用户直接输入指令,也支持脚本化编程以实现自动化使命。其核心作用包罗解析和执行用户命令、管理进程的启动与制止、协调输入输出重定向(如管道|和文件重定向>)、维护环境变量及工作目次状态,并通过元字符扩展(如通配符*)简化文件操纵。作为体系资源的调理中介,Shell将用户请求转化为体系调用,毗连应用步伐与底层硬件,同时支持背景使命、作业控制及复杂脚本逻辑,是体系管理和开发服从的核心工具。
6.2.2 壳的处理处罚流程
Shell的处理处罚流程始于读取用户输入或脚本内容,首先举行词法解析和语法分析,分割命令与参数,处理处罚引号及转义符。随后展开环境变量更换(如$PATH)和元字符更换(如通配符*扩展为文件名),解析重定向符号并调解输入输出流。若命令为内置功能(如cd),则直接由Shell进程执行;若为外部步伐(如ls),则通过fork创建子进程并exec加载目标步伐,父进程通过wait等待子进程结束并捕获退出状态。流程结束后,Shell重置标准流并返回提示符,循环等待下一条指令,同时维护会话环境的一致性。
6.3 Hello的fork进程创建过程
当用户在Shell中执行./hello时,fork进程创建过程通过fork()体系调用生成一个与Shell父进程完全相同的子进程,该子进程独立拥有新的进程ID,但继续父进程的内存、环境变量和文件描述符等资源。这一过程仅复制Shell的上下文,尚未运行目标步伐,子进程与父进程在现在处于并行状态,等待进一步指令。
6.4 Hello的execve过程
子进程调用execve()体系调用,将hello可执行文件的代码段、数据段等内容加载到其内存空间,彻底覆盖原有的Shell步伐副本,重置堆栈并初始化寄存器,终极跳转到hello的入口函数(如main())。这一过程完全更换了子进程的执行逻辑,使其蜕变为一个专属于hello的新进程,而父进程则通过wait()等待子进程结束并接纳其资源。
6.5 Hello的进程执行
进程调理通过时间片轮转或优先级计谋分配CPU资源。进程运行时处于用户态,其上下文(寄存器、步伐计数器等)存储于PCB中;当时间片耗尽或触发停止(如I/O请求),CPU通过硬件停止切换到核心态,内核保存当进步程上下文并运行调理算法,从就绪队列选择新进程,加载其上下文到寄存器并切换回用户态执行。核心态完成资源管控和状态切换,用户态则专注步伐执行,两者通过体系调用/停止协作,实现进程高效切换与CPU利用率优化。
6.6 hello的异常与信号处理处罚
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理处罚的。
步伐运行过程中可以按键盘,如不绝乱按,包罗回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理处罚。
6.6.1 hello执行过程中可能会出现的异常
- 停止(异步异常):处理处罚器外部I/O装备引起;
- 陷阱(同步异常):有意的,执行指令的结果;
- 故障(同步异常):不是有意的,但可能被修复;
- 制止(同步异常):非故意,不可恢复的致命错误造成。
6.6.2 hello执行过程中可能会产生的信号
- 停止:信号SIGTSTP,默认行为是制止直到下一个SIGCONT;
- 制止:信号SIGINT,默认行为是制止。
6.6.3 对异常和信号的处理处罚方式
如图6.1所示,在任何情况下,当处理处罚器检测到有变乱发生时,它就会通过一张叫做异常表(exception table) 的跳转表,举行一个间接过程调用(异常),到一个专门设计用来处理处罚这类变乱的操纵体系子步伐(异常处理处罚步伐(exception handler)) 。当异常处理处罚步伐完成处理处罚后,根据引起异常的变乱的范例,会发生以下 3种情况中的一种:
1) 处理处罚步伐将控制返回给当前指令 Icurr 即当变乱发生时正在执行的指令。
2) 处理处罚步伐将控制返回给Inext , 假如没有发生异常将会执行的下一条指令。
3) 处理处罚步伐制止被停止的步伐[1]。
6.6.4 hello步伐运行以及异常与信号的处理处罚方式
在执行过程中按下CTRL-z终端驱动步伐向前台进程组(子进程hello地点组)发送SIGTSTP信号,子进程收到后默认停息执行(进入TASK_STOPPED状态)。
如图6.2所示,按下CTRL-z后进程制止运行,状态为STOPPED。
CTRL-z后运行ps命令,体系体现各进程信息,如图6.3所示。
CTRL-z后运行jobs命令,体现当前会话内全部被停息(如按Ctrl-Z)或背景运行(以&结尾启动)的使命列表,如图6.4所示,进程hello处于被停息状态。
CTRL-z后运行pstree命令,以树状图形式展示进程间的父子关系,直观出现进程的派生层级,如图6.5所示。
CTRL-z后运行fg命令,将背景使命或停息的使命切换至前台继续执行,需指定使命编号,如图6.6所示。
CTRL-z后运行kill-9命令,向进程发送SIGKILL信号杀死进程,如图6.7所示。
按下CRTL-c后终端发送SIGINT信号给前台进程组,子进程hello默认制止执行,如图6.8所示。
6.7本章小结
本章简述了进程的概念和作用、异常与信号的处理处罚方式。并结合详细步伐hello简述了进程执行过程以及对异常和信号的处理处罚。
(第6章2分)
第7章 hello的存储管理
7.1 hello的存储器地址空间
结合hello说明逻辑地址、线性地址、假造地址、物理地址的概念。
7.1.1 逻辑地址
逻辑地址是步伐编译后生成的地址,比方代码中循环变量i或函数printf的地址,它们存在于步伐的视角中,是相对于代码段或数据段的偏移量。
7.1.2线性地址
当步伐被加载到内存时,操纵体系通过分段机制将逻辑地址转换为线性地址(在x86架构中体现为“段基址+偏移量”),但现代操纵体系通常简化分段,逻辑地址与线性地址往往直接对应。
7.1.3 假造地址
假造地址是进程运行时所见的一连内存空间,比方hello进程通过argv[1]访问命令行参数时,参数在进程独立的假造地址空间中“看似一连”,实际可能分散在物理内存或磁盘互换区。
7.1.4 物理地址
操纵体系通过页表将假造地址映射到物理地址(即实际内存芯片上的硬件地址),比方sleep(atoi(argv[4]))执行时,代码指令地点的假造地址会被内存管理单元(MMU)转换为物理地址,确保CPU正确访问内存中的数据。
7.2 Intel逻辑地址到线性地址的变换-段式管理
Intel处理处罚器的段式管理通过段选择符(段寄存器)和段描述符实现转换。逻辑地址由“段选择符:偏移量”构成,CPU根据段选择符在全局描述符表(GDT)或局部描述符表(LDT)中查找对应的段描述符,提取段基址后与偏移量相加,生成线性地址。段描述符定义了内存段的基址、界限和访问权限,完成地址空隔断离与保护。
7.3 Hello的线性地址到物理地址的变换-页式管理
线性地址到物理地址的转换通过页式管理实现。操纵体系将线性地址分别为页目次索引、页表索引和页内偏移。CPU利用CR3寄存器定位页目次的基址,通过页目次索引找到对应的页表,再根据页表索引定位物理页框的基址,终极将基址与页内偏移相加得到物理地址。页表项中保存了权限标志(如存在位、读写权限),确保内存访问的安全性和隔离性。此过程通过多级页表结构实现假造内存到物理内存的映射。
7.4 TLB与四级页表支持下的VA到PA的变换
在 TLB(转换后备缓冲器) 和四级页表的支持下,假造地址(VA)到物理地址(PA)的转换过程如下:
- TLB查询:CPU首先用假造地址的高位(VPN)查询TLB,若命中则直接获取物理页框号(PPN),跳过页表遍历,极大加速转换。
- 四级页表遍历(若TLB未命中):
- 从CR3寄存器获取顶级页目次(PML4)基址。
- 依次用假造地址的4级索引(PML4→PDPT→PD→PT)逐级查页表项(PTE),终极得到PPN。
- 将PPN与假造地址的页内偏移合并,生成物理地址(PA)。
- 权限与异常检查:每级PTE验证权限位(如存在位、读写权限),若非法则触发缺页异常或保护错误。
- TLB更新:转换完成后,将VPN-PPN映射存入TLB,供后续快速访问。
7.5 三级Cache支持下的物理内存访问
在 三级Cache(L1/L2/L3) 的支持下,CPU访问物理内存的流程如下:
- L Cache查询:CPU核首先用物理地址查询私有L Cache(通常分指令/数据Cache)。若命中(数据存在),直接以极低延迟(约-4周期)返回数据。
- L Cache查询(L1未命中):访问同核共享的L Cache。若命中,数据返回CPU并回填L1 Cache(约10-0周期)。
- L Cache查询(L2未命中):访问多核共享的L Cache。若命中,数据返回并依次回填L2/L1 Cache(约0-50周期)。
- 主存访问(L3未命中):通过内存控制器访问DRAM主存(约200+周期),数据加载后按计谋回填L3→L2→L1 Cache,并触发Cache更换计谋(如LRU)淘汰旧数据。
- 一致性维护:多核场景下,通过MESI协议维护多级Cache间数据一致性,确保多核读写操纵的原子性和可见性。
7.6 hello进程fork时的内存映射
调用 fork() 创建子进程时,内核复制父进程的地址空间结构(页表、假造内存地区等),但物理内存页通过写时复制(Copy-On-Write, COW) 共享。父子进程的代码段、数据段等只读部分直接共享物理页;当任一进程实验修改共享页时,触发缺页异常,内核再分配新物理页并复制内容,实现内存隔离。
7.7 hello进程execve时的内存映射
调用 execve() 加载新步伐时,内核清空原进程的地址空间,重新构建内存映射:
- 代码段(text):映射可执行文件的代码区(只读)。
- 数据段(data/bss):映射初始化/未初始化数据区(读写,私有)。
- 堆/栈:分配匿名页(动态增长)。
- 动态库:通过 mmap 加载共享库(如 libc.so)到共享内存区。
原进程的资源(如打开文件)可能保存,但代码、数据、堆栈等完全更换为新步伐的内容
7.8 缺页故障与缺页停止处理处罚
当步伐访问的假造地址未映射到物理内存(页表项存在位为0,或权限不符)时,CPU触发缺页故障,产生缺页停止。缺页停止的处理处罚流程如下:
- 停止响应
CPU停息当进步程,切换到内核态,执行缺页停止处理处罚步伐。
- 错误诊断
- 检查假造地址的正当性(是否属于进程地址空间,权限是否匹配)。
- 若非法(如越界访问或权限错误),制止进程或发送信号(如SIGSEGV)。
- 页面加载
- 正当缺页:定位所需页面在磁盘的位置(互换空间或文件体系)。
- 物理页分配:从空闲链表中分配物理页帧,若内存不敷则触发页面置换(如LRU算法)。
- 数据加载:从磁盘读取页面到物理页帧,若为写时复制(COW)则复制原页内容。
- 页表更新
修改页表项,将假造地址映射到新分配的物理页帧,并设置存在位及权限标志。
- 恢复执行
重新执行触发缺页的指令,此时假造地址已映射到有效物理内存。
7.9动态存储分配管理
Printf会调用malloc,请简述动态内存管理的基本方法与计谋。(此节讲堂没有讲授,选做,不算分)
7.10本章小结
本章关注hello的内存管理,先容了hello从加载到执行过程中涉及到的地址变换以及内存管理过程。
(第7章 2分)
结论
用盘算机体系的语言,逐条总结hello所履历的过程。
你对盘算机体系的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
从盘算机体系视角,hello步伐的生命周期履历以下核心过程:
- 编译时处理处罚:通过预处理处罚器展开宏与头文件,编译器生成与机器相关的汇编指令,汇编器编码为可重定位目标文件,链接器完成符号解析与地址重定位,构建可执行ELF文件。
- 进程创建:Shell通过fork创建子进程副本,execve加载hello代码段至假造地址空间,初始化堆栈并建立页表映射,形成独立进程控制块(PCB)。
- 运行时管理:MMU通过四级页表与TLB实现VA到PA转换,三级Cache优化物理内存访问;动态链接库通过PLT/GOT实现延迟绑定。
- 执行控制:CPU按指令流水线执行逻辑,处理处罚缺页停止与信号(如SIGINT),内核调理器分配时间片实现进程切换。
- 资源接纳:进程制止后,内核释放物理页帧、文件描述符等资源,扫除假造内存映射,完成020生命周期闭环。
看似简朴的步伐,其背后是设计精妙逻辑美满的盘算机体系的支撑。通过完资本文,我加深了对于盘算机体系的理解,运用课程的知识对详细步伐举行了完备的分析,收获颇丰!
(结论0分,缺失-1分)
附件
列出全部的中心产物的文件名,并予以说明起作用。
文件名
| 作用
| hello.i
| 预处理处罚后文件
| hello.s
| 汇编文件
| hello.o
| 可重定位的可执行文件
| hello
| 链接后的可执行文件
| hello_elf.txt
| hello.o readelf结果
| hello_elf2.txt
| hello readelf结果
| hello_obj.txt
| hello.o反汇编结果
| hello_obj2.txt
| hello 反汇编结果
|
(附件0分,缺失 -1分)
参考文献
为完资本次大作业你翻阅的书籍与网站等
- (美)兰德尔. E. 布莱恩特等著;龚奕利,贺莲译.深入理解盘算机体系(原书第3版).北京:机械工业出版社, 2016.7
(参考文献0分,缺失 -1分)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |