ICS大作业论文

计算机系统基础课程报告

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oyh7luGZ-1685065631031)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.001.jpeg “hit04”)]

计算机系统

大作业

题 目 程序人生-Hello’s P2P

专 业 未来技术学院人工智能2+x

学   号 2021112905

班   级 21WL023

学 生 徐浩铭

指 导 教 师 郑贵滨

计算机科学与技术学院

2023年5月

摘 要

本文研究了hello.c在Linux系统下的整个生命周期,了解了在一个进程中从文本文件到可执行文件计算机系统的作用。了解到预处理、编译、汇编、链接等过程,同时也有关于进程、存储器等知识。本文整体对csapp的内容进行了回顾复习。

**关键词:**深入理解计算机系统,程序生命周期;

(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)

**

目 录

第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. Hello简介

要将 hello.c 变成一个可执行的目标程序,必须要经过 预处理器、编译器、汇编器和链接器 的处理。这是Program过程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p8Ao6jZ8-1685065631033)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.002.png “20201210194936958”)]

图1-1 Program的过程

然后是Process过程。在 shell 命令行中输入命令:$./hello.o;shell 命令行解释器构造 argv 和 envp;调用 fork 函数创建子进程,其地址空间与shell父进程完全相同,包括只读代码段、读写数据段、堆及用户栈等;调用 execve 函数在当前进程(新创建的子进程)的上下文中加载并运行hello 程序。将hello中的.text节、.data 节、.bss 节等内容加载到当前进程的虚拟地址空间中;调用 hello 程序的 main 函数,传入之前构造好的 argv、envp,hello 程序开始运行

1.2 环境与工具

硬件环境:Intel® Core™ i7-11800H CPU @ 2.30GHz 16GB RAM

软件环境:Windows 11 64位 Ubuntu 22.04.1

调试工具:GCC,EDB,GDB,Objdump,readelf,Code:Blocks

1.3 中间结果

hello.ihello.c的预处理结果
hello.s通过hello.i编译得到
hello.o通过hello.s汇编得到
hello通过hello.o链接得到
hello_elf.txthello.o用readelf读取得到的ELF格式信息
hellooasm.txthello.o反汇编后得到的反汇编文件
helloout_elf.txt由hello可执行文件生成的.elf文件
helloasm.txthello可执行文件反汇编后得到的反汇编文件

1.4 本章小结

本章对hello.c程序的P2P过程进行了完全回顾,同时通过汇编和反汇编的方式保存了程序编译运行的过程的中间文件。

第2章 预处理

(0.5分)

2.1 预处理的概念与作用

以下格式自行编排,编辑时删除

预处理是在编译过程中的一个阶段,用于对源代码进行一系列的文本替换和操作,以生成最终的编译代码。预处理器是编译器的组成部分之一,它会根据指定的预处理指令和宏定义,对源代码进行处理。

预处理的作用是在编译之前对源代码进行文本处理,根据指定的预处理指令和宏定义,对代码进行替换、包含和条件编译等操作,以生成最终的编译代码。这样可以提高代码的可读性、可维护性,并根据不同的需求生成不同的编译结果。

2.2在Ubuntu下预处理的命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f8eaIAzJ-1685065631033)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.003.png)]

图2-1 预处理命令

2.3 Hello的预处理结果解析

hello.i文件有很长,有三千多行。因为在预处理过程中,将<stdio.h>、<unistd.h>、<stdlib.h>三个头文件都加载到hello.i中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwSZo9CV-1685065631033)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.004.png)]

图2-2 预处理结果解析

Hello.i文件末尾就是main函数,中间全是头文件展开的内容。

2.4 本章小结

本章我们了解程序预处理的流程和作用,展示了linux命令行中预处理过程,简析了hello.i文件的内容。

第3章 编译

(2分)

3.1 编译的概念与作用

编译(Compilation):在这个阶段,编译器会将预处理后的文件作为输入,对其进行词法分析、语法分析和语义分析,生成对应的中间表示(如抽象语法树、中间代码等)。然后,编译器将中间表示转化为汇编语言代码,这些汇编语言代码通常保存在以".s"为扩展名的文件中。

作用:将高级语言转化为机器更容易理解的汇编语言,更符合机器的工作逻辑

3.2 在Ubuntu下编译的命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ae6cMpsz-1685065631034)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.005.png)]

图3-1 编译命令

3.3 Hello的编译结果解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wJG3dNfU-1685065631034)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.006.png)]

图3-2 hello.s图示

3.3.1 数据

(1)字符串常量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HlOIGIS6-1685065631034)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.007.png)]

图 3-3 字符串常量

在.rodata中直接存储,\XXX为UTF-8编码,一个汉字对应三个字节。

在引用时给出地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6l4vt4tb-1685065631035)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.008.png)]

图 3-4 引用字符串

(2)局部变量

在栈中保存,开始时直接用立即数0对i进行赋值,然后跳到.L3中。之后用for循环进行累加,只要小于等于8都跳转到.L3中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pnekFLZI-1685065631035)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.009.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z10Uuz1C-1685065631035)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.010.png)]

图 3-5 局部变量i

(3)argc,argv

是main函数传入的参数,本质上也是局部变量,保存在栈中。

3.3.2 赋值

用mov类指令,可以是直接赋立即数,也可以将某一内存处的值赋到某一寄存器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bi8rqfXx-1685065631036)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.011.png)]

图3-6 对局部变量赋值

3.3.3 算术操作

使用算术addl指令,令寄存器%ebp中保存的值每次循环完加上立即数1.达到i++的效果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8cLFq34F-1685065631036)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.012.png)]

图 3-7 算术操作

3.3.4 关系操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RERpvUDM-1685065631036)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.013.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wl1PdeEK-1685065631037)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.014.png)]

图 3-8 关系操作指令

用cmpl指令,比较两个数的大小。第一张图接着jne指令,故是比较%edi寄存器的值与4相等,若不等则跳转.L6。第二张图是比较%ebp是否小于等于8, 若小于等于则跳转.L3。

对应源程序 if(argc!=4) 和 for(i=0;i<9;i++)

3.3.5 数组操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r5cKSTGf-1685065631038)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.015.png)]

图3-9 数组操作

%rbx保存argv数组首地址,这两句代码意思是argv[1],argv[2], 对应源代码

printf(“Hello %s %s\n”,argv[1],argv[2]); 中argv[1], argv[2]的两个参数

3.3.6 控制转移

如3.3.4图所示,在进行cmpl之后设置一个条件码,根据条件码进行转移,一图若等于4,则跳到.L2,二图若小于等于8则跳到.L4。

3.3.7 函数操作

调用了printf、exit、sleep、getchar函数

利用call指令来调用相应的函数,使用ret进行返回。

在传参过程中,函数的传参遵循以下规则:当函数参数小于6个时,使用寄存器:rdi、rsi、rdx、rcx、r8、r9;当大于六个时,前六个参数放入寄存器中,多余的放入栈中。

  1. 调用printf函数:

有三个参数"Hello %s %s\n", argv[1], argv[2] 分别存放在rsi、rdx、rcx

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PBkvAWbk-1685065631038)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.016.png)]

图3-10 调用printf函数

  1. 调用exit函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3cThq3Uj-1685065631038)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.017.png)]

图3-11 调用exit函数

(3) 调用atoi和sleep函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8VAAJwjw-1685065631039)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.018.png)]

图 3-12 调用atoi和sleep函数

函数返回,程序使用指令ret从调用的函数中返回,函数出栈,并且还原栈帧

3.4 本章小结

本章通过对编译文件的深度解析,具体地了解了编译过程是如何将源代码转换为汇编代码的,并分析了各数据结构和操作。

第4章 汇编

(2分)

4.1 汇编的概念与作用

汇编:指将编译后的.s文件翻译为机器语言二进制的可重定位目标.o文件。输入的是汇编语言书写的源程序,输出的是用机器语言表示的目标程序。

作用:将文本类代码转换成机器能直接运行的二进制代码。

4.2 在Ubuntu下汇编的命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lcbTAL4C-1685065631039)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.019.png)]

图4-1 汇编命令

4.3 可重定位目标elf格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fv7zg7Rb-1685065631040)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.020.png)]

图4-2 查看ELF文件

生成的ELF文件如图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJ5bCTjm-1685065631041)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.021.png)]

图4-3 ELF文件图示

ELF头如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y0YZ5bKM-1685065631042)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.022.png)]

图4-4 ELF头

ELF头以一个16字节的序列开始。其描述了生成该文件的系统的字的大小和字节顺序。剩下的部分包含帮助链接器语法分析和解释目标文件的信息。

节头如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ykKLdc51-1685065631043)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.023.png)]

图4-5 节头

节区中包含目标文件中的所有信息,除了:ELF 头部、程序头部表格、节区头部表格。

重定位节:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xGn6TMgt-1685065631043)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.024.png)]

图4-6 重定位节

重定位节从左至右依次是需要被修改的引用的节偏移,符号索引信息,类型,value,符号名,用来对被修改引用的值做偏移调整的有符号常数。

符号表:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lneCbEbn-1685065631043)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.025.png)]

图4-7 符号表

目标文件的符号表中包含用来定位、重定位程序中符号定义和引用的信息。符号表 索引是对此数组的索引。索引 0 表示表中的第一表项,同时也作为 定义符号的索引。

4.4 Hello.o的结果解析

机器语言是一种使用二进制数码表示的指令集体系,每条机器指令对应一条汇编语言指令。机器语言的操作数与汇编语言不同,汇编语言可以操作内存、寄存器和立即数。而机器语言只包含二进制数。

在与"hello.s"进行比较时,当进行函数调用时,"hello.s"直接使用"call"指令后跟函数名来进行调用。而在反汇编代码中,"call"指令使用相对于"main"函数的偏移位置。

当进行分支转移时,“hello.s"使用”.L1"、“.L2”、"L3"等段名称来表示跳转目标。而在反汇编代码中,分支指令使用的是相对于当前指令之前的偏移地址来表示跳转目标。

4.5 本章小结

本章对汇编生成可重定位目标文件hello.o进行分析,介绍了ELF文件格式及其具体内容,比较了hello.s与hello.o的不同,对机器代码和汇编语言有了更深的理解。

第5章 链接

(1分)

5.1 链接的概念与作用

链接是将多个目标文件或库文件合并为一个可执行文件或共享库的过程。链接器(linker)负责执行链接操作。链接的主要目的是解决符号引用(symbol references)的问题。

在编译过程中,源代码被编译为目标文件(object file),每个目标文件包含了已编译代码的机器语言指令以及符号的引用。符号可以是变量、函数、类等标识符。

链接的作用是将编译过程中生成的多个目标文件整合起来,解决符号引用、重定位和重复定义等问题,生成最终可执行文件或共享库。它是将程序的各个模块连接在一起,使程序能够正确地执行的关键步骤。

5.2 在Ubuntu下链接的命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A7p1C6RQ-1685065631044)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.026.png)]

图5-1 链接的命令

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

首先生成elf的文本文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dJ3qqoqP-1685065631044)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.027.png)]

图5-2 生成elf的文本文件

ELF头:指可执行与可链接格式(Executable and Linkable Format,ELF)文件中的一个特殊部分,它包含了关于该文件的一些重要信息。根据给定的"hello_elf.txt"中的内容,ELF头的信息种类与其中描述的基本相同。

ELF头中的"Magic"字段是一个16字节序列,描述了生成该文件的系统的字大小和字节顺序。这些信息基本上是固定的,很少发生改变。

除了"Magic"字段外,与"hello_elf.txt"中的ELF头相比,程序头和节头的数量增加了,并且具有新的入口地址。程序头表(Program Header Table)描述了程序运行时所需的各个段(Segment)的信息,包括加载地址、大小等。节头表(Section Header Table)则包含了各个节(Section)的信息,如代码段、数据段等。这些新增的表格提供了更详细的文件结构和布局信息,使得链接器和加载器能够更准确地处理文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZEpXhvqY-1685065631044)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.028.png)]

图5-3 ELF头

节头:节头包含了文件中出现的各个节的意义,包括类型、位置和大小信息。这里的节头比之前的数量变多。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5wQO15VX-1685065631045)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.029.png)]

图5-4 节头

程序头:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TAB1YnVt-1685065631045)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.030.png)]

图5-6 程序头

重定位:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ND2mDweR-1685065631045)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.031.png)]

图5-7 重定位信息

5.4 hello的虚拟地址空间

使用edb加载hello,查看本进程的虚拟地址空间各段信息。

虚拟地址空间查看是从0x400000到0x405000

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o3nvY4wx-1685065631045)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.032.png)]

图 5-7 虚拟地址空间

.interp段:该段内保存有动态链接库的位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gwcTymcM-1685065631046)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.033.png)]

图 5-8 .interp段位置

.text段: 代码存放段

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OE7jQntM-1685065631046)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.034.png)]

图 5-9 .text段位置

5.5 链接的重定位过程分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NBeNtSM3-1685065631046)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.035.png)]

图 5-10 生成重定位文件

链接的过程:

通过该命令生成链接后的反汇编文件,先比较链接后的反汇编文件和hello.o的不同,链接之后生成的hello中加入了共享库。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w0E7Y4Qq-1685065631047)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.036.png)]

图 5-11 函数图示

函数调用指令在链接过程中会经历变化。链接器会解析重定位条目,对call指令后的字节代码进行修改,使其指向目标函数的地址与下一条指令的地址之差。这样,汇编代码中的函数调用指令就得到了完整的地址。

另外,函数的跳转指令也会发生变化。链接器会计算相对距离,并修改对应位置的字节代码,使其指向过程链接表中相应函数与下一条指令的相对地址。这样,在执行跳转指令时,程序会根据PLT中的地址进行跳转到目标函数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uNu0uteK-1685065631047)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.037.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hjBz2cNO-1685065631048)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.038.png)]

图 5-12 call和跳转指令的变化

5.6 hello的执行流程

通过edb来运行hello,输入相关参数,运行情况如下:

ld-2.27.so!_dl_start、 ld-2.27.so!_dl_init、hello!_start、 libc-2.27.so!__libc_start_main、-libc-2.27.so!__cxa_atexit、 -libc-2.27.so!__libc_csu_init 、hello!_init、 libc-2.27.so!_setjmp、 -libc-2.27.so!_sigsetjmp、 --libc-2.27.so!__sigjmp_save、 hello!main、hello!puts@plt、

hello!exit@plt、 *hello!printf@plt、 *hello!sleep@plt、 *hello!getchar@plt、

ld-2.27.so!_dl_runtime_resolve_xsave、 -ld-2.27.so!_dl_fixup、 --ld-2.27.so!_dl_lookup_symbol_x、 libc-2.27.so!exit

5.7 Hello的动态链接分析

用edb打开hello,根据hello的ELF格式中.rela.plt的位置,找到需要动态链接的函数地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-omgT5lDW-1685065631048)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.039.png)]

图 5-13 重定位节图示

在do_init调用之前对应区域为空。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iMPkNhzl-1685065631048)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.040.png)]

图 5-14 do_init前

在调用之后,可以看到对应区域有了相关内容,动态链接成功。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QaWTSRJE-1685065631049)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.041.png)]

图 5-15 do_init后

分析hello程序的动态链接项目,通过edb调试,分析在dl_init前后,这些项目的内容变化。要截图标识说明。

5.8 本章小结

本章中主要通过分析hello的ELF格式内容回顾了链接的过程, 学习了解了虚拟内存,动态链接以及重定位等内容。

第6章 hello进程管理

(1分)

6.1 进程的概念与作用

进程是计算机中正在运行的程序的实例。它是操作系统进行资源分配和调度的基本单位。每个进程都有自己的地址空间、程序代码、数据、打开的文件、处理器状态等。

进程的作用包括资源分配、并发执行、进程间通信、隔离和保护、错误处理和异常处理等功能,是操作系统实现多任务和多用户环境的基础。。

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

壳(Shell)是计算机操作系统中提供用户与操作系统内核进行交互的命令行解释器。其中,Bash(Bourne Again SHell)是一种常见的壳程序,广泛用于类Unix系统中,如Linux和macOS。

Bash壳的作用是接收用户输入的命令,并将其解释为操作系统能够理解和执行的指令。它提供了一个命令行界面,让用户可以通过输入命令来控制和管理计算机系统。Bash壳还提供了一些特性和功能,如变量、条件语句、循环、函数等,使得用户可以编写脚本来批量执行命令和自动化任务。

处理流程:提示符显示、用户输入命令、命令解析、命令执行、输出显示、等待下一条命令。在处理流程中,Bash壳还支持一些高级特性,如通配符扩展、输入输出重定向、管道、环境变量等,它们提供了更强大的命令行操作能力。

6.3 Hello的fork进程创建过程

当在shell中输入"./hello"时,shell会认为"hello"是一个可执行文件,而不是shell的内置命令。此时,shell会使用fork()函数创建一个新的进程。

新创建的子进程几乎与父进程相同,但不完全相同。子进程会得到与父进程用户级虚拟地址空间相同的一个副本,包括代码段、数据段、堆、共享库以及用户栈等。

虽然子进程与父进程共享一些资源,但它们是独立的进程,有着不同的进程ID(PID)。这个PID是操作系统为每个进程分配的唯一标识符。

因此,在输入"./hello"后,shell会创建一个新的子进程,并为子进程提供与父进程相同的虚拟地址空间的副本。这样,子进程可以执行"hello"可执行文件的代码,并与父进程并行运行,但它们具有不同的PID和独立的进程执行环境。

6.4 Hello的execve过程

execve()函数在当前进程的上下文中加载并运行一个新程序。它会覆盖当前进程的地址空间,但不会创建一个新的进程。因此,新的程序仍然具有相同的进程ID(PID),并且继承了调用execve()函数时已打开的所有文件描述符。

通过调用execve()函数,可以加载并运行可执行目标文件(例如"hello"),并传递参数列表(argv)和环境变量(envp)。新程序会取代当前进程的代码、数据和堆栈,成为当前正在执行的程序。

值得注意的是,execve()函数只有在出现错误时才会返回到调用程序。一旦execve()函数成功加载并执行新程序,它将永远不会返回到原来的调用位置。因此,execve()函数通常被用来在当前进程中切换到不同的可执行程序,实现程序的动态加载和替换。

6.5 Hello的进程执行

进程调度是操作系统中的关键任务,它决定了哪个进程在特定时刻获得处理器的使用权。在进行进程调度时,涉及到进程的上下文信息和时间片的概念。

每个进程都有一个上下文信息,包括程序计数器(指向下一条要执行的指令)、寄存器值、栈指针等。当一个进程被抢占或挂起时,它的上下文信息被保存,以便稍后恢复执行。这个上下文切换过程通常由操作系统负责。

进程调度时,操作系统会根据调度算法从就绪队列中选择一个合适的进程,以获得处理器的使用权。每个进程被分配一个时间片,表示它能连续执行的时间量。当进程的时间片用尽后,操作系统会中断该进程的执行,并将处理器分配给下一个就绪进程。

在进行进程调度时,还涉及到用户态和核心态之间的转换。当进程在用户态执行应用程序代码时,它只能执行受限的指令和访问有限的资源。但是,当进程需要进行与操作系统相关的操作时,如系统调用或访问内核资源,它必须切换到核心态。

核心态下,进程具有更高的特权级别,可以执行特权指令和访问受限资源,如操作系统内核数据结构和设备驱动程序。在用户态和核心态之间切换时,操作系统会保存和恢复进程的上下文信息,以确保进程在切换后能够继续执行。

6.6 hello的异常与信号处理

1.正常运行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fog8eRqD-1685065631049)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.042.png)]

图 6-1 正常运行情况

2.ctrl-c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bEHt139e-1685065631049)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.043.png)]

图 6-2 ctrl-c情况

按下ctrl-c直接终止进程

3.ctrl-z

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N30IFuhS-1685065631050)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.044.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8bgW4956-1685065631050)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.045.png)]

图 6-3 输入ps和fg情况

按下ctrl-z后会发送一个SIGTSTP信号到前台进程组中的每个进程,程序会被挂起,但并未结束,可以用ps看到还存在,用fg指令可以继续执行。输入jobs可以查看后台有正在运行的命令,用pstree可以看到正在执行的hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f52ZV8Rr-1685065631050)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.046.png)]

图 6-4 输入jobs情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DNnuUc1M-1685065631050)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.047.png)]

图 6-5 输入pstree情况

4.回车

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FjlBtere-1685065631051)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.048.png)]

图 6-6 输入空格情况

多输出几行空格,对程序并不影响

5.不停乱按

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDaWR1I0-1685065631051)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.049.png)]

图 6-7 不停乱按情况

当第一次按到enter之后,getchar读到换行,后面输入的都会在hello结束后做为命令行的输入。但是最后一次循环时打印不了,进程卡死。

6.7本章小结

本章介绍了进程的概念和作用,shell-bash的概念,以及hellofork、execve函数的原理与过程,还简要概述了hello程序的执行过程和对异常与信号的处理结果。

第7章 hello的存储管理

( 2分)

7.1 hello的存储器地址空间

逻辑地址是程序生成的与段相关的偏移地址部分,由选择符和偏移量组成。它可以用于定位程序中的特定数据或指令,例如在hello.asm中使用的相对偏移地址。

线性地址是指地址空间中的连续整数地址。当地址空间的地址按顺序排列且没有间隔时,称之为线性地址空间。

虚拟地址是在带有虚拟内存的系统中生成的地址。在这种系统中,CPU从一个具有2的n次方个地址的地址空间中生成虚拟地址。虚拟地址空间可以简化处理,并允许对内存进行透明的管理和保护。

物理地址是计算机系统中主存储器的实际地址。主存以连续的字节单元组成的数组形式存在,每个字节都有一个唯一的物理地址。

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

段式管理是将一个程序划分为多个逻辑实体(段)进行存储的管理方式,与程序的模块化概念密切相关。这种管理方式通过使用段表来实现,段表包括段号或段名、段起点、装入位、段长度等信息。此外,还需要主存占用区域表和主存可用区域表来辅助管理。

逻辑地址由两部分组成,即段标识符和段内偏移量。段标识符是一个16位的字段,也被称为段选择符。其中,前13位是一个索引号,用于标识特定的段。后面的三位包含一些硬件细节,用于支持地址转换和访问权限等操作。

段式管理通过将程序划分为多个段,每个段作为一个逻辑实体进行独立的存储和管理,可以提高程序的模块化性,方便代码的组织和维护。逻辑地址的组成方式使得程序可以根据段标识符和段内偏移量来访问特定段中的数据或指令。整个过程依赖于段表的管理和逻辑地址的转换,以实现对段的正确访问和保护。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QBqQGl7l-1685065631051)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.050.png)]

通过索引号,可以使用段标识符的前13位直接在段描述符表中找到一个具体的段描述符,该描述符用于描述一个段。

在进行索引时,还需要考虑两个重要的字段:

  1. TI(Table Indicator):通过TI的值来判断选择全局描述符表(当TI=0时,选择GDT)或选择局部描述符表(当TI=1时,选择LDT)。
  2. RPL(Requested Privilege Level):用于判断请求的权限等级。RPL的值决定了进程的重要等级,其中RPL=00表示最高级别的内核权限,而RPL=11表示最低级别的用户状态权限。

通过使用索引号和这两个字段,可以找到相应的段描述符,并从中获取段基址。然后,将段基址与偏移量相结合,就可以得到线性地址和虚拟地址。

7.3 Hello的线性地址到物理地址的变换-页式管理

线性地址(也称为虚拟地址)由虚拟页号(VPN)和虚拟页偏移(VPO)组成。在内存管理单元(MMU)的帮助下,通过页表进行地址翻译,将虚拟地址空间映射到物理地址空间(线性地址即为虚拟地址,VA)。CPU中的页表基址寄存器(PTBR)指向当前页表,用于地址转换。

虚拟地址的长度为n位,由两个部分组成:一个长度为p位的虚拟页面偏移(VPO)和一个长度为(n-p)位的虚拟页号(VPN)。MMU根据虚拟页号(VPN)选择适当的页表条目(PTE)。通过将页表条目中的物理页号(PPN)和虚拟地址中的虚拟页面偏移(VPO)连接起来,就得到相应的物理地址。

简而言之,通过虚拟页号(VPN)和虚拟页偏移(VPO),线性地址(虚拟地址)在内存管理单元(MMU)的帮助下进行地址转换。MMU利用页表,通过选择正确的页表条目(PTE),将虚拟地址映射到相应的物理地址。这个过程实现了虚拟地址空间到物理地址空间的映射。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hGqfrbBn-1685065631052)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.051.png)]

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

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

翻译后备缓冲器(TLB)是内存管理单元(MMU)中的一个小型缓存,用于加速对页表条目(PTE)的查询,从而提高地址翻译的速度。

在Core i7处理器中,地址翻译过程采用了四级页表结构(L1页表、L2页表、L3页表、L4页表),将虚拟地址转换为物理地址。36位的虚拟页号(VPN)被划分为四个9位的片段(VPN1、VPN2、VPN3、VPN4),每个片段用作访问对应级别的页表的偏移量。控制寄存器CR3中存储了L1页表的物理地址。

通过VPN1可以访问L1页表中的页表条目(PTE),每个PTE包含了对应L2页表的基地址。通过VPN2可以访问L2页表中的PTE,以此类推进行多级页表的遍历,直到最终获得物理页号(PPN)。

简而言之,TLB是MMU中的一个缓存,用于加速地址翻译。Core i7处理器采用了四级页表结构,并通过多级页表的遍历将虚拟地址转换为物理地址。不同的VPN片段用于访问对应级别的页表,通过连续的页表访问最终获取物理页号。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CR58xlHx-1685065631052)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.052.png)]

图 7-3 TLB与四级页表支持下的VA到PA的变换

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

地址翻译在高速缓存查找之前进行。页表条目(PTE)可以被缓存,就像其他数据字一样。

  1. CPU生成一个虚拟地址。
  2. MMU从翻译后备缓冲器(TLB)中获取相应的PTE。当TLB未命中时,MMU必须从一级缓存(L1缓存)中获取相应的PTE,并将新获取的PTE存放到TLB中,可能会覆盖一个已存在的条目。PTE命中。
  3. MMU将之前CPU生成的虚拟地址翻译为一个物理地址,并将该物理地址发送到高速缓存/主存。
  4. 高速缓存/主存将所请求的数据字返回给CPU。

7.6 hello进程fork时的内存映射

当当前进程调用fork()函数时,内核为新进程创建各种数据结构,并为其分配一个唯一的进程标识符(PID)。为了为新进程创建虚拟内存,内核复制了当前进程的内存管理结构(如mm_struct)以及区域结构和页表。在创建完成后,内核将两个进程中的每个页面标记为只读,并将每个区域结构标记为私有的写时复制。

当**fork()在新进程中返回时,新进程的虚拟内存与调用fork()**时当前进程的虚拟内存完全相同。通过写时复制机制,当两个进程中的任意一个进行写操作时,新的页面会被创建,从而为每个进程保持了私有地址空间的抽象概念。

7.7 hello进程execve时的内存映射

执行execve函数来加载并运行hello程序需要以下几个步骤:

  1. 删除已存在的用户区域:首先,删除当前进程hello虚拟地址空间中已存在的区域结构,清除之前的用户数据。
  2. 映射私有区域:为新程序的代码、数据、bss和栈区域创建新的私有、写时复制的区域结构。代码和数据区域会被映射到hello文件中的**.text.data段。bss区域是由二进制零填充的,会映射到匿名文件中,并且其大小在hello**程序中指定。栈和堆区域也会被映射为请求二进制零,并且初始长度为零。
  3. 映射共享区域:如果hello程序与共享对象或库(例如标准C库libc.so)链接,那么这些对象会被动态链接到hello程序,并映射到用户虚拟地址空间的共享区域中。
  4. 设置程序计数器:最后,execve函数会设置当前进程上下文中的程序计数器,将其指向代码区域的入口点,以便开始执行新程序的指令流程。

7.8 缺页故障与缺页中断处理

DRAM缓存不命中被称为缺页。在给定的示例中,CPU引用了VP3中的一个字,但是VP3并未缓存在DRAM中。地址翻译硬件从内存中读取PTE3,并通过有效位判断VP3未被缓存,并触发了一个缺页异常。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G0TV1N5s-1685065631052)(Aspose.Words.8965426e-0e2b-42d7-95e4-a9fb90e76b78.053.png)]

图 7-4 缺页异常图示

缺页异常会调用内核中的缺页异常处理程序。该程序会选择一个牺牲页,本例中为存放在PP3中的VP4。如果VP4已经被修改,内核会将其复制回磁盘。无论是否复制到磁盘,内核都会修改VP4的页表条目,反映出VP4不再缓存在主存中。

接下来,内核从磁盘复制VP3到内存中的PP3,并更新PTE3,然后返回。当异常处理程序返回时,它会重新启动导致缺页的指令,该指令会重新发送导致缺页的虚拟地址给地址翻译硬件。然而,现在VP3已经缓存在主存中,所以地址翻译硬件能够正常处理页命中。

这样,在缺页之后,我们的示例页表的状态已经更新,以反映VP3的缓存情况。

7.9本章小结

本章通过介绍了逻辑地址、线性地址、虚拟地址和物理地址的概念。它详细解释了Intel架构下逻辑地址到线性地址的变换过程,即段式管理,以及Hello程序中线性地址到物理地址的变换过程,即页式管理。讨论了TLB(翻译后备缓冲器)和四级页表对虚拟地址到物理地址的转换提供的支持。

此外,还介绍了三级Cache对物理内存访问的支持。随后,探讨了Hello进程在进行fork和execve时的内存映射过程,包括删除已存在的用户区域、映射私有区域和映射共享区域的步骤。

最后,讨论了缺页故障和缺页中断的处理过程,当DRAM缓存不命中时会发生缺页异常,内核会通过选择牺牲页和将页从磁盘复制到内存来处理缺页异常。

结论

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

用计算机系统的语言,逐条总结hello所经历的过程。

你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。

Hello的一生可以总结为以下过程:

  1. 编译阶段:源程序文件经过预处理、编译、汇编和链接等步骤生成可执行文件hello。
  2. 运行阶段:
    1. 用户在命令行中输入./hello来运行可执行文件。
    2. Shell解释器创建一个新的进程作为hello的子进程。
  3. 子进程创建:
    1. Shell调用fork函数来创建一个新的子进程,该子进程是hello的副本。
    2. 子进程继承了父进程的代码、数据和资源。
  4. 加载运行阶段:
    1. Shell调用execve函数,将可执行文件hello加载到子进程的内存中。
    2. 子进程获得了独立的虚拟地址空间,具有自己的私有区域。
  5. 运行阶段:
    1. 在运行过程中,hello可能需要进行内存分配、信号处理以及其他操作。
    2. 它执行自己的代码逻辑,完成特定的任务。
  6. 结束阶段:
    1. 当hello进程执行完毕或者发生错误时,它会终止运行。
    2. 父进程(Shell)通过回收子进程来释放子进程占用的资源。
    3. 内核删除为hello进程创建的所有数据结构,回收相应的内存和系统资源。

深切感悟:经过一学期计算机系统的学习,加之这学期同时在学计组,我对计算机的底层和体系结构有了一个大致的认识,在之后的专业课学习过程中我会更加认真的去学习计算机的基本知识,把现在学的知识贯通起来,然后把csapp未学完的内容继续看完。

此外,感谢老师和助教一学期的辛苦付出,祝你们假期愉快!

附件

列出所有的中间产物的文件名,并予以说明起作用。

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

hello.ihello.c的预处理结果
hello.s通过hello.i编译得到
hello.o通过hello.s汇编得到
hello通过hello.o链接得到
hello_elf.txthello.o用readelf读取得到的ELF格式信息
hellooasm.txthello.o反汇编后得到的反汇编文件
helloout_elf.txt由hello可执行文件生成的.elf文件
helloasm.txthello可执行文件反汇编后得到的反汇编文件

参考文献

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

[1] 深入理解计算机系统第三版

[2] ELF文件详解-初步认识https://blog.csdn.net/daide2012/article/details/7306520 4?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166892333716782412547584%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=166892333716782412547584&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-73065204-null-null.142v65control,201v3add_ask,213v2t3_control2&utm_term=elf&spm=1018.2226.3001.4187

(参考文献0分,缺失 -1分)

- 16 -
hello.o链接得到|
|hello_elf.txt|hello.o用readelf读取得到的ELF格式信息|
|hellooasm.txt|hello.o反汇编后得到的反汇编文件|
|helloout_elf.txt|由hello可执行文件生成的.elf文件|
|helloasm.txt|hello可执行文件反汇编后得到的反汇编文件|

参考文献

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

[1] 深入理解计算机系统第三版

[2] ELF文件详解-初步认识https://blog.csdn.net/daide2012/article/details/7306520 4?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166892333716782412547584%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=166892333716782412547584&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-73065204-null-null.142v65control,201v3add_ask,213v2t3_control2&utm_term=elf&spm=1018.2226.3001.4187

(参考文献0分,缺失 -1分)

- 16 -

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值