2022春 程序人生-Hello’s P2P

计算机系统

大作业

题 目 程序人生-Hello’s P2P
专 业 计算学部
班   级 2003010
学 生 魏欣然    
指 导 教 师 郑贵滨

计算机科学与技术学院
2021年5月
摘 要
本文主要讲述hello程序从预处理到最后运行之间每一步的具体实现过程,在过程中所产生的文件的内容分析,以及进程管理、存储管理、I/O管理的相关信息。
关键词:预处理;编译;汇编;链接;进程管理;存储管理;I/O管理

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

目 录

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

第1章 概述
1.1 Hello简介
P2P(Program to Process):hello.c经过预处理得到hello.i文件、编译生成hello.s的汇编文件、再经过as的处理便为可重定位目标文件hello.o、最后链接生成可执行文件hello。用户输入./hello命令开始执行程序,shell通过fork函数创建一个子进程,再由子进程执行execve函数加载hello的过程。

020(Zero-0 to Zero-0):execve执行hello程序后,内核为hello进程映射虚拟内存。在hello进入程序入口后,hello相关的数据就被内核加载到物理内存中,hello程序开始正式被执行。为了让hello正常执行,内核还需要为hello分配时间片、逻辑控制流。最后,当hello运行结束,终止成为僵尸进程后,由shell负责回收hello进程,删除与hello有关的数据内容。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
硬件环境:X64 CPU、8GRAM、238GHD Disk
软件环境:Windows10;VirtualBox;Ubuntu 20.04
开发、调试工具:visual studio2022、gcc、edb、gdb
1.3 中间结果
hello.c 源程序
hello.i 预处理后程序
hello.s 编译后的汇编程序
hello.o 汇编后的可重定位目标程序
hello_elf.txt hello.o的elf格式
hello.asm hello.o的反汇编代码
hello 可执行程序
hello1_elf.txt hello的elf格式
hello2.txt hello的反汇编代码
1.4 本章小结
本章主要包括hello的简介,实验时的软硬件环境及使用工具,以及实验中间产生的文件。
(第1章0.5分)

第2章 预处理
2.1 预处理的概念与作用
1.概念:预处理器根据以字符#开头的命令,修改原始的C程序
2.作用:扩展源代码,插入所有用#include命令指定的文件,并扩展所有用#define声明指定的宏,得到一个以.i作为文件扩展名的另一个C程序。

2.2在Ubuntu下预处理的命令
hello.c->hello.i命令如下:
在这里插入图片描述

图2.2.1 hello.c->hello.i命令

得到一个hello.i文件:
在这里插入图片描述

图2.2.2 hello.i文件
2.3 Hello的预处理结果解析
hello.i部分内容截图如下:
在这里插入图片描述

图2.3.1 hello.i部分内容截图

hello的预处理结果解析:
可以看到,相较于之前的hello.c文件内容,hello.i文件内容增加了很多行,其主要是对原程序的宏进行了宏展开,将#include的内容包含到了文件中,但是在文件最后部分,可以找到main函数如下图所示:
在这里插入图片描述

图2.3.2 main函数截图
可以观察到预处理并没有对这部分代码进行改动。
2.4 本章小结
本章主要介绍了预处理的概念及其作用,通过对hello.c预处理生成hello.i文件,查看hello.i文件,解析其预处理结果实际上是对原程序的展开。

(第2章0.5分)

第3章 编译
3.1 编译的概念与作用
1.概念:编译器将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。
2.作用:生成的hello.s文件每条语句都以一种文本格式描述了一条低级机语言指令,汇编语言为不同高级语言的不同编译器提供了通用的输出语言,更利于机器理解。
3.2 在Ubuntu下编译的命令
hello.c->hello.i命令如下:
在这里插入图片描述

图3.2.1 hello.c->hello.i命令

得到一个hello.s文件:
在这里插入图片描述

图3.2.2 hello.s文件
3.3 Hello的编译结果解析
1.汇编指令
(1).file声明源文件
(2).text代码节
(3).section.rodata只读代码段
(4).align数据或者指令的地址对齐方式
(5).string声明一个字符串
(6).globl声明全局变量
(7).type声明一个符号是数据类型还是函数类型
2.数据
(1)字符串
在.c文件中,可以看出有字符串“用法: Hello 学号 姓名 秒数!\n”和 “Hello %s %s\n”,字符串储存在只读代码段中
在.s文件中,字符串位置如下:
在这里插入图片描述

图3.3.1 字符串位置截图
\347\224\250\346\263\225这种格式,其实是汉字被编码成UTF-8格式,一 个汉字占据3个字节,每个字节用\分割

(2)整数
<1>int i
i是一个局部变量,被储存在栈-4(%rbp)处,由于i是int类型,故占四个 字节
在这里插入图片描述

图3.3.2
<2>int argc
argc同样作为一个int类型的局部变量,作为第一个输入的参数,开始存放在%edi中,后被赋值到-20(%rbp)
在这里插入图片描述

图3.3.3
<3>其他常数
其他的常数在.s文件中,以立即数($number)形式出现

(3)数组char *argv[]
char *argv[]是main函数的第二个参数,数组存放在栈%rbp中
在这里插入图片描述

图3.3.4
当想访问argv数组的内容时,首先获取起始地址,然后计算偏移量,访问下一个元素,如下图所示:
在这里插入图片描述

图3.3.5

3.赋值
在hello程序中,赋值操作有给i赋值为0,对应为:
在这里插入图片描述

图3.3.6
图中将立即数0赋值给i,由于i是int类型,四个字节,故mov后缀为l

4.类型转换
在hello程序中,类型转换语句如下

利用atoi函数,把字符串argv[3]转换成整型,对应为:
在这里插入图片描述

图3.3.7

5.算术操作
(1)在hello程序中,算术操作有i++,对应到汇编语言为:
在这里插入图片描述

图3.3.8
-4(%rbp)中存储每次+1操作后i的新值
(2)开辟新的栈空间
在这里插入图片描述

图3.3.9
(3)计算偏移量
在这里插入图片描述

图3.3.10
6.关系操作
(1)if(argc!=4)
在汇编语言中对应语句如下:
在这里插入图片描述

图3.3.11
(2)for(i=0;i<8;i++)
在汇编语言中对应语句如下:
在这里插入图片描述

图3.3.12
7.数组/指针/结构操作
首先获取argv数组的首地址,然后对首地址加8字节得到argv[1]的地址,然后再通过argv[1]中的内容找到对应的字符串,存储在寄存器%rax之中。
在这里插入图片描述

图3.3.13
8.控制转移
(1)if(argc!=4)
在这里插入图片描述

图3.3.14
通过比较argv与4的数值,设置条件码,25行判断条件码ZF位是否为0,若相等,跳转至.L2位置;否则,不相等,不跳转继续执行下一条指令。
(2)for(i=0;i<8;i++)
在这里插入图片描述

图3.3.15
同样进行比较,当i<=7(i<8)时跳转至.L4处,否则继续执行下一行。
9.函数操作
(1)main函数
main函数被存储在.text节中,有两个参数,分别为命令行传入的argc和argv[],开始被保存在寄存器%rdi和%rsi中
在这里插入图片描述

图3.3.16
(2)printf函数
第一处调用由于只有一串字符串,故直接调用puts函数,此时参数存放在%edi中。

在第二处调用中,包括三个参数,分别保存在%rdx、%rsi、%rdi中
在这里插入图片描述

图3.3.17
(3)exit函数
先给%edi赋值为1,调用exit
在这里插入图片描述

图3.3.18
(4)atoi函数
将第四个参数存到%rax中,再调用atoi
在这里插入图片描述

图3.3.19
(5)sleep函数
调用atoi后的返回值赋值到%edi中,作为sleep函数的参数,再调用sleep函数。
在这里插入图片描述

图3.3.20
(6)getchar函数
由于getchar函数没有参数,故可直接调用
在这里插入图片描述

图3.3.21
3.4 本章小结
本章主要介绍了编译的概念及其作用,通过指令将hello.i编译生成hello.s文件,查看hello.s文件,解析hello的编译结果,分析其数据与操作的具体实现。
(第3章2分)

第4章 汇编
4.1 汇编的概念与作用
1.概念:汇编器将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可 重定位目标程序的格式,并将结果保存在目标文件hello.o中。
2.作用:将编译器产生的汇编语言进一步翻译为计算机可以理解的机器语言, 使其在链接后能被机器识别并执行。
4.2 在Ubuntu下汇编的命令
hello.s->hello.o指令如下:
在这里插入图片描述

图4.2.1 hello.s->hello.o指令

得到一个hello.o文件:
在这里插入图片描述

图4.2.2 hello.o文件
4.3 可重定位目标elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
在Ubuntu中利用readelf命令来查看ELF:
在这里插入图片描述

图4.3.1 readelf命令

得到hello_elf.txt:
在这里插入图片描述

图4.3.2 hello_elf.txt

分析:
1.ELF头
由一个16字节的magic序列开始,此序列描述了生成该文件的系统的字的大小和字节顺序。ELF头剩下的部分包含帮助连接器语法分析和解释目标文件的信息。其中包括ELF头的大小、目标文件类型、机器类型、字节头部表的文件偏移,以及节头部表中条目的大小和数量等信息。不同节的位置和大小是有节头部表描述的,其中目标文件中每个节都有一个固定大小的条目。
在这里插入图片描述

图4.3.3 ELF头
2.节头部表:包含各个节的名称,类型,地址,偏移量,大小等
在这里插入图片描述

图4.3.4 节头部表

3…rela.text节(重定位节):包括各函数信息
在这里插入图片描述

图4.3.5 .rela.text节

4.符号表符;包括符号的大小,类型等信息
在这里插入图片描述

图4.3.6 符号表符
4.4 Hello.o的结果解析
在Ubuntu中用命令objdump -d -r hello.o > hello.asm生成hello.asm:
在这里插入图片描述

图4.4.1 objdump命令

1.hello.o反汇编代码与hello.s的不同
(1)hello.o反汇编在指令前增加了其十六进制表示,即机器语言。
在这里插入图片描述

图4.4.2
(2)hello.s中操作数为十进制,而hello.o的反汇编中操作数为十六进制
(3)跳转语句中,hello.o的反汇编跳转不需要段名称,而是直接通过地址跳转。
在这里插入图片描述

图4.4.3
(4)在hello.s中,call指令后通常为函数名称,而在hello.o的反汇编中,call指令后为下一条指令的地址。
在这里插入图片描述

图4.4.4
2.机器语言的构成
机器语言是机器能直接识别的程序语言或指令代码,无需经过翻译,每一操作码在计算机内部都有相应的电路来完成它,或指不经翻译即可为机器直接理解和接受的程序语言或指令代码。机器语言使用绝对地址和绝对操作码。不同的计算机都有各自的机器语言,即指令系统。从使用的角度看,机器语言是最低级的语言。
计算机是通过执行指令来处理各种数据的。为了指出数据的来源、操作结果的去向及所执行的操作,一条指令必须包含下列信息:
(1)操作码。它具体说明了操作的性质及功能。一台计算机可能有几十条至几百条指令,每一条指令都有一个相应的操作码,计算机通过识别该操作码来完成不同的操作。
(2)操作数的地址。CPU通过该地址就可以取得所需的操作数。
(3)操作结果的存储地址。把对操作数的处理所产生的结果保存在该地址中,以便再次使用。
(4)下条指令的地址。执行程序时,大多数指令按顺序依次从主存中取出执行,只有在遇到转移指令时,程序的执行顺序才会改变。

4.5 本章小结
本章主要介绍了汇编的概念与作用,通过指令将hello.s汇编生成hello.o文件,查看hello.o的反汇编文件,解析hello.o的结果与hello.s的不同。
(第4章1分)

第5章 链接
5.1 链接的概念与作用
1.概念:链接是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载到内存并执行。
2.作用:链接器使得分离编译成为可能,我们不用将一个大型的应用程序组织为一个巨大的源文件,而是可以把它分解为更小、更好管理的模块,可以独立地修改和编译这些模块
5.2 在Ubuntu下链接的命令
ld链接命令如下:
在这里插入图片描述

图5.2.1 ld链接命令

生成一个可执行目标文件hello:
在这里插入图片描述

图5.2.2 可执行目标文件hello
5.3 可执行目标文件hello的格式
命令:
在这里插入图片描述

图5.3.1 readelf命令

生成一个hello1_elf.txt文件:
在这里插入图片描述

图5.3.2 hello1_elf.txt

1.ELF头:hello是一个可执行目标文件,入口点地址不再是0x0,节头数量也发生了变化。
在这里插入图片描述

图5.3.3 ELF头

2.节头:节头数量发生变化,每个节的地址不再是0,而是根据自身大小加上偏移量。
在这里插入图片描述

图5.3.4 节头

3.重定位节:重定位节的偏移量与hello.o不同
在这里插入图片描述

图5.3.5 重定位节
4.符号表:多出了.dynsym节,里面存放的是通过动态链接解析出的符号,即程序引用的头文件中的函数
在这里插入图片描述

图5.3.6 符号表

5.4 hello的虚拟地址空间
使用edb加载hello,从Data Dump窗口看虚拟地址空间
1.ELF头:ELF从0x400000开始
在这里插入图片描述

图5.4.1 ELF
2.对应hello1_elf.txt的节头表的地址以及偏移量,可以对应在edb中找到各节的位置,例如:.text节的偏移量为000010f0,在edb中:
在这里插入图片描述

图5.4.2 .text
5.5 链接的重定位过程分析
使用如下命令:
在这里插入图片描述

图5.5.1 objdump命令

生成一个hello2.txt文件:
在这里插入图片描述

图5.5.2 hello2.txt文件

1.hello的反汇编代码中增加了函数的汇编代码
在这里插入图片描述

图5.5.3

2.hello的反汇编代码中有确定的虚拟地址,而hello.o中均为0,寻址方式采用虚拟地址寻址
在这里插入图片描述

图5.5.4

3.增加了.init和.plt节
在这里插入图片描述

图5.5.5

objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。
重定位:将多个单独的代码节和数据节合并为单个节,将符号从它们在.o文件中的相对位置重新定位到可执行文件中的最终绝对内存位置,用它们的新位置,更新所有对这些符号的引用。
5.6 hello的执行流程
ld-2.31.so!_dl_start
ld-2.31.so!_dl_init
hello!_start
libc-2.31.so!_libc_start_main
libc-2.31.so!_cxa_atexit
hello!_libc_csu_int
libc-2.31.so!_setjmp
hello!main
libc-2.27.so!exit
5.7 Hello的动态链接分析
PLT:PLT是一个数组,其中每个条目是16字节代码。PLT[0]是一个特殊条目,它跳转到动态链接器中。每个被可执行程序调用的库函数都有它自己的PLT条目,每个条目都负责调用一个具体的函数。PLT[[1]]调用系统启动函数 (__libc_start_main)。从PLT[[2]]开始的条目调用用户代码调用的函数。
GOT:GOT是一个数组,其中每个条目是8字节地址。和PLT联合使用时,GOT[0]和GOT[[1]]包含动态链接器在解析函数地址时会使用的信息。GOT[[2]]是动态链接器在ld-linux.so模块中的入口点。其余的每个条目对应于一个被调用的函数,其地址需要在运行时被解析。

1.通过查看hello的ELF文件获取.got.plt位置如下:
在这里插入图片描述

图5.7.1

2.比对前后变化:
dl_init前:
在这里插入图片描述

图5.7.2

dl_init后:
在这里插入图片描述

图5.7.3

5.8 本章小结
本章主要介绍了链接的概念与作用,如何在Ubuntu下链接,分析了hello的elf格式文件,同时也分析了hello的虚拟地址空间,重定位,以及hello的执行流程,并且比较了hello.o的反汇编和hello的反汇编。
(第5章1分)

第6章 hello进程管理
6.1 进程的概念与作用
1.概念:进程的经典定义就是一个执行中程序的实例。系统中的每个程序都运行在某个进程的上下文中。
2.作用:进程提供了一个假象,好像我们的程序是系统中当前运行的唯一的程序一样,程序好像独占地使用处理器和内存,处理器好像无间断地一条接一条地执行我们程序中的指令。
6.2 简述壳Shell-bash的作用与处理流程
1.作用:shell 是一个交互型应用级程序,代表用户运行其他程序,提供了一个界面,用户通过访问这个界面访问操作系统内核的服务。
2.处理流程:
(1)从终端读入输入的命令。
(2)将输入字符串切分获得所有的参数
(3)如果是内置命令则立即执行
(4)否则调用相应的程序执行
(5)shell 应该接受键盘输入信号,并对这些信号进行相应处理
6.3 Hello的fork进程创建过程
1.输入命令“./hello 120L020324 魏欣然 1”,shell读取命令,并进行分析
2.首先这不是一条内置指令,所以shell会认为执行可执行文件hello
3.此时,shell会fork一个子进程来独立运行hello程序,新创建的子进程几乎但不完全与父进程相同。
在这里插入图片描述

图6.3.1 运行
6.4 Hello的execve过程
为了运行hello程序,shell还需要调用execve函数,execve加载并运行程序hello
execve函数:int execve(char *filename, char *argv[], char *envp[])
filename:可执行文件 argv:参数列表 envp:环境变量列表
execve函数运行过程:
1.删除已存在的用户区域,删除之前进程在用户部分中已存在的结构。
2.创建一组新的代码、数据、堆端,并初始化为0
3.映射共享区域,将新的代码和数据段初始化为可执行文件中的内容
4.设置程序计数器,使其指向代码区的入口点
6.5 Hello的进程执行
(以下格式自行编排,编辑时删除)
结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换等等。
1.进程上下文信息:通过上下文切换,控制流通从一个进程传递到另一个进程
在这里插入图片描述

图6.5.1 上下文切换

2.进程时间片:一个进程执行它的控制流的一部分的每一时间段叫做时间片。
3.hello程序分析:当hello程序开始时,运行在用户模式,内核将为其保存一个上下文,执行函数sleep时,系统将陷入内核状态,利用上下文切换转移到新进程,sleep函数执行结束后,再通过上下文切换返回到hello函数中
6.6 hello的异常与信号处理
1.可能出现的异常:
(1)中断:来自处理器外部的I/O设备的信号的结果(输入Ctrl-C、Ctrl-V等),返回给下一条指令。
(2)陷阱:是有意的异常,是执行一条指令的结果,返回给下一条指令。陷阱最重要的用途是在用户程序和内核之间提供一个像过程一样的接口,叫做系统调用。
(3)故障:由错误引起,它可能能够被故障处理程序修正。如果能够修正,重新执行引起故障的指令,否则终止程序。
(4)终止:不可恢复的致命错误造成的结果,通常是一些硬件错误,终止处理程序从不将控制返回给应用程序。
2.可能产生的信号
SIGINT,SIGSTP,SIGCONT,SIGKILL等
3.程序运行过程中的操作
(1)乱按:如果乱按的过程中包括回车,那么乱按的内容将会在该程序结束之后作为命令输入
在这里插入图片描述

图6.6.1 乱按

(2)Ctrl-Z:按下Ctrl-Z后,内核会发送一个SIGTSTP信号到前台进程组的每个进程,默认情况下,结果是停止(挂起)前台作业。
在这里插入图片描述

图6.6.2 按Ctrl-Z
(3)Ctrl-C:按下Ctrl-C会导致内核发送一个SIGINT信号到前台进程组中的每个进程,默认情况下,是终止前台作业。
在这里插入图片描述

图6.6.3 按Ctrl-C

(4)ps jobs pstree fg kill等
ps:当前在运行的进程及其pid
jobs:所有在执行的指令
pstree:所有进程之间的父子关系树

在这里插入图片描述

图6.6.4

fg:
在这里插入图片描述

图6.6.5

kill:杀死某一进程
在这里插入图片描述

图6.6.6

6.7本章小结
本章主要介绍了进程的概念及作用,Shell-bash的作用与处理流程,fork进程、exceve过程、进程执行过程以及异常与信号处理。
(第6章1分)

第7章 hello的存储管理
7.1 hello的存储器地址空间
1.逻辑地址:一个逻辑地址由两部份组成,段标识符和段内偏移量,是CPU生成的地址,在内部和编程使用,并不唯一。
2.线性地址:逻辑地址到物理地址变换之间的中间层。在分段部件中逻辑地址是段中的偏移地址,然后加上基地址就是线性地址。
3.虚拟地址:保护模式下程序访问存储器所用的逻辑地址
4.物理地址:在存储器里以字节为单位存储信息,为正确地存放或取得信息,每一个字节单元给以一个唯一的存储器地址,称为物理地址。

在这里插入图片描述

图7.1.1 逻辑地址
在hello2.txt文件中,其中标记部分即为逻辑地址,再加上段地址就是虚拟地址,经过地址翻译可以得到物理地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理
逻辑地址由段号(段名)和段内地址(段内偏移量)所组成。段标识符是由一个16位长的字段组成,称为段选择符。其中前13位是一个索引号。后面3位包含一些硬件细节。如图:
在这里插入图片描述

图7.2.1 逻辑地址结构
段式管理是通过段表进行的,包括段号(段名),段起点,装入位,段的长度等。程序通过分段划分为多个块,如代码段,数据段,共享段等。
在这里插入图片描述

图7.2.2 段式管理
7.3 Hello的线性地址到物理地址的变换-页式管理
线性地址即虚拟地址(VA)到物理地址(PA)之间的转换通过分页机制完成,而分页机制是对虚拟地址内存空间进行分页。
CPU中的一个控制寄存器,页表基址寄存器指向当前页表,n位的虚拟地址包含两部分:一个p位的虚拟页面偏移和一个(n-p)位的虚拟页号。MMU利用VPN来选择适当的PTE。将页表条目中的物理页号和虚拟地址中的VPO串联起来,就得到相应的物理地址。
在这里插入图片描述

图7.3.1 页式管理
7.4 TLB与四级页表支持下的VA到PA的变换
一到三级页表中存放的数据是指向下一级页表的首地址,而不是物理页号。逐步访问到第四级页表,第四级页表中装的就是物理页号,通过第四级页表读出的物理页号链接上虚拟地址中的VPO获得物理地址。
在这里插入图片描述

图7.4.1 四级页表

1~3级页表条目格式:
在这里插入图片描述

图7.4.2 1~3级页表条目格式

4级页表条目格式:
在这里插入图片描述

图7.4.3 4级页表条目格式
7.5 三级Cache支持下的物理内存访问
利用得到的物理地址,首先根据组索引定位组;检查集合中的任何行是否有匹配的标记如果:是 + 行有效——命中;最后定位数据:从块偏移开始的数据
在这里插入图片描述

图7.5.1 cache访问

如果不命中,就要向下一级的cache寻找数据,如果三级都没有,则要向内存中寻找。找到之后更换cache中的空闲块,若没有空闲块,则需要更新一个块的数据。
7.6 hello进程fork时的内存映射
内存映射:将虚拟内存区域与磁盘上的对象关联起来,用于初始化这个虚拟内存区域的内容。
虚拟内存和内存映射解释fork函数如何为每个新进程提供私有的虚拟地址空间。
1.为新进程创建虚拟内存
▪ 创建当前进程的mm_struct、vm_area_struct链表和页表的原样副本。
▪ 两个进程中的每个页面都标记为只读
▪ 两个进程中的每个区域结构(vm_area_struct)都标记为私有的写时复制(COW) 2.在新进程中返回时,新进程拥有与调用fork的父进程相同的虚拟内存
3.随后的写操作会通过写时复制机制创建新页面
7.7 hello进程execve时的内存映射
execve函数在当前进程中加载并运行新程序a.out的步骤: 
1.删除已有页表和结构体vm_area_struct链表
2.创建新的页表和结构体vm_area_struct链表
▪ 代码和初始化的数据映射到.text和.data区(目标文件提供)
▪ .bss和栈映射到匿名文件
3.设置PC,指向代码区域的入口点
▪ Linux根据需要换入代码和数据页面
在这里插入图片描述

图7.7.1 内存映射
7.8 缺页故障与缺页中断处理
缺页: 引用虚拟内存中的字,不在物理内存中 (DRAM 缓存不命中)。
处理过程:
1.判断虚拟地址是否合法,若不合法发出段错误
2.判断访问地址是否合法,若不合法终止程序
3.缺页异常处理程序选择一个牺牲页,如果这个页面已经牺牲过了则会把它换到磁盘,换入新的页面并更新页表。之后返回原来的进程,再次执行引起缺页的命令,就不会再产生缺页中断了。
7.9动态存储分配管理
动态内存分配器维护着进程的一个虚拟内存区域,称为堆。分配器有两种类型:显示分配器和隐式分配器,显式分配器:要求应用显式地释放任何已分配的块, 隐式分配器: 应用检测到已分配块不再被程序所使用,就释放这个块。
动态内存管理的基本方法与策略:
1.隐式空闲链表:一个块是由一个字的头部、有效载荷、可能的一些额外的填充,以及在块的结尾处的一个字的脚部组成的。头部编码了这个块的大小(包括头部和所有的填充),以及这个块是已分配的还是空闲的
在这里插入图片描述

图7.9.1 隐式空闲链表

2.显式空闲链表:将空闲块组织成链表形式的数据结构。堆可以组织成一个双向空闲链表,在每个空闲块中,都包含一个pred(前驱)和succ(后继)指针
在这里插入图片描述

图7.9.2 显式空闲链表

3.放置策略:
(1)首次适配:从头开始搜索空闲链表,选择第一个合适的空闲块:可以取总块数(包括已分配和空闲块)的线性时间,但是会在靠近链表起始处留下小空闲块的“碎片”。
(2)下一次适配:和首次适配相似,只是从链表中上一次查询结束的地方开始,优点是比首次适应更快:避免重复扫描那些无用块。但是一些研究表明,下一次适配的内存利用率要比首次适配低得多。
(3)最佳适配:查询链表,选择一个最好的空闲块适配,剩余最少空闲空间,优点是可以保证碎片最小——提高内存利用率,但是通常运行速度会慢于首次适配。
4.分割策略
(1)什么时候开始分割空闲块?
(2)能够容忍多少内部碎片?
5.合并策略
(1)立即合并: 每次释放都合并
(2)延迟合并:直到需要才合并,提高释放的性能。
7.10本章小结
本章主要介绍了hello的存储器地址空间、段式管理、页式管理,TLB与四级页表支持下的VA到PA的变换,三级Cache支持下的物理内存访问,hello进程fork和execve时的内存映射,以及缺页故障、缺页中断处理和动态存储分配管理等。
(第7章 2分)

第8章 hello的IO管理
8.1 Linux的IO设备管理方法
设备的模型化:文件
设备管理:unix io接口
一个Linux文件就是一个 m 字节的序列,所有的I/O设备(网络、磁盘、终端)都被模型化为文件,这种将设备优雅地映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,称为Unix I/O。
8.2 简述Unix IO接口及其函数
1.打开文件:通知内核,准备访问该文件,成功返回文件描述符,失败返回-1
函数:int open(char *filename, int flags, mode_t mode);
2.关闭文件:成功返回0,失败返回1
函数:int close(int fd);
3.读文件:读文件从当前文件位置复制字节到内存位置,然后更新文件位置,返回值表示的是实际传送的字节数量
函数:ssize_t read(int fd, void *buf, size_t n);
4.写文件:写文件从内存复制字节到当前文件位置,然后更新文件位置,返回值表示的是从内存向文件fd实际传送的字节数量
函数:ssize_t write(int fd, const void *buf, size_t n);
8.3 printf的实现分析
1.printf函数体
在这里插入图片描述

图8.3.1 printf函数

(1)传递参数中的…表示参数个数不确定
(2)将…中的第一个参数的量赋给arg
(3)调用vsprintf函数
在这里插入图片描述

图8.3.2 vsprintf函数

(4)vsprintf的作用就是格式化。它接受确定输出格式的格式字符串fmt。用格式字符串对个数变化的参数进行格式化,产生格式化输出,返回值为串的长度。
(5)调用write函数:将长度为i的buf输出,在write函数中,将栈中参数放入寄存器,ecx是字符个数,ebx存放第一个字符地址
在这里插入图片描述

图8.3.3 write函数
(6)sys_call函数:显示格式化了的字符串
在这里插入图片描述

图8.3.4 sys_call函数
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
getchar通过调用read函数从缓冲区中读入一行,并返回读入的第一个字符,若读入失败则返回EOF
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
本章主要介绍了Linux的IO设备管理方法、Unix IO接口及其函数、printf以及getcahr函数的实现分析。
(第8章1分)
结论
1.预处理:对hello.c预处理生成hello.i文件
2.编译:hello.i编译生成汇编文件hello.
3.汇编:hello.s经过汇编得到可重定位目标文件hello.o
4.链接:hello.o经过链接得到可执行文件hello
5.运行:输入命令./hello 120L020324 魏欣然运行程序,shell调用fork函数创建子进程,调用execve函数加载运行hello程序,当hello进入函数入口开始运行时,虚拟内存会产生缺页异常,从而将hello程序所需要使用的信息交换到主存,并为其分配物理地址,通过cache来访问,运行过程中,还可能收到各种信号,需要进行信号处理,最后hello程序结束,被父进程回收。

感悟:从前只了解.c程序代码,通过这门课程的学习,了解到了一个程序从创建到运行,中间需要经历如此多环环相扣、严谨细致的过程,同时也让我明白编程时要考虑面向cpu等的优化方法。
(结论0分,缺失 -1分,根据内容酌情加分)

附件
hello.c 源程序
hello.i 预处理后程序
hello.s 编译后的汇编程序
hello.o 汇编后的可重定位目标程序
hello_elf.txt hello.o的elf格式
hello.asm hello.o的反汇编代码
hello 可执行程序
hello1_elf.txt hello的elf格式
hello2.txt hello的反汇编代码
(附件0分,缺失 -1分)

参考文献
为完成本次大作业你翻阅的书籍与网站等
[1] Randal E.Bryant .深入理解计算机系统(第三版). 机械工业出版社
[2] https://www.cnblogs.com/pianist/p/3315801.html
(参考文献0分,缺失 -1分)

【6层】一字型框架办公楼(含建筑结构图、计算书) 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
1、资源项目源码均已通过严格测试验证,保证能够正常运行;、 2项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值