收藏官网首页
查看: 4277|回复: 0

计算机系统-大作业

77

主题

89

帖子

1938

积分

金牌会员

Rank: 6Rank: 6

积分
1938
跳转到指定楼层
楼主
 楼主| 发表于 2022-5-30 11:45:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
教您5分钟接入机智云,实现傻瓜式开发
本帖最后由 我是吃货 于 2022-5-30 11:49 编辑

本文以hello.c文件为案例,详细地分析了程序在Linux、Window操作系统下的运行过程,分别从硬件、软件、用户、内核等各个方面阐述了程序的运行过程,并在适当的过程中给出相应的程序截图。本文主要按照《CS:APP》的章节顺序进行展开,从低层次到高层次逐渐理解操作系统的各个机制和工作原理。

关键词:操作系统、Linux、程序
目 录
第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章 概述
1.1 Hello简介
根据Hello的自白,利用计算机系统的术语,简述Hello的P2P,020的整个过程。
在编辑器中完成Hello.c的代码编写之后(Program),IDE或者编译器(GCC等)会在执行的时候进行预处理、编译、汇编、链接操作,转化为可执行的二进制文件,该文件会在用户申请执行的时候被操作系统内核(OS)通过fork创建子程序,同时调用execve函数载入硬件执行,从而形成了一个进程(Progress).在未申请执行的时候,项目(Program)不会申请占用任何计算机资源(除去存储该执行文件的硬盘资源),在Program在载入为进程(Progress)执行时才会申请使用计算机资源(CPU、缓存等),在进程结束之后,父进程或者操作系统回收之后,该项目也不会占用任何计算机资源。

1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
硬件:X86 CPU、20G以上硬盘、16x2G内存
软件:Window 10 操作系统、VM虚拟机、Ubuntu 20.0操作系统、泰山服务器
开发与调试工具:GCC、GUN、vscode、Visual Studio、Olly Debug、edb

1.3 中间结果
列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。
hello.c: c语言源文件,存储项目代码
hello.i:hello.c预处理得到的文件
hello.s:hello.i编译得到的文件
hello.o:hello.s汇编得到的文件
hello:hello.o链接得到的可执行文件
Hello.out:hello反汇编得到的可重定位文件
Hello.txt: objdump 反汇编Hello.out生成的文件

1.4 本章小结
第一章主要提供论文的基本信息以及实验的基础环境,对计算机系统有一个大致的了解,同时能够对计算机系统的各个过程、各类文件有一个比较清晰的认识。
(第1章0.5分)

第2章 预处理

2.1 预处理的概念与作用
预处理是指预处理器对源文件由预处理器(Preprocessor)对程序源代码进行的处理。这个过程并不对程序的源代码语法进行解析,但它会把源代码分割或处理成为特定的符号为下一步的编译做准备工作。
预处理会将所有以#开头的命令行(包括条件编译指令、头文件指令以及预定义宏)替换为程序员的定义格式,同时c语言还提供了__FILE__、LINE、__TIME__等预订宏。他们会在预处理的时候被预处理器替换为其他命令。
预处理是为接下来编译器对代码进行编译做准备的,对于用户来说,预处理能够简化代码格式,同时可以使用条件预处理防止文件重复,使得文件层次更加清晰。

2.2在Ubuntu下预处理的命令
(以下格式自行编排,编辑时删除)
gcc -E Hello.c -o Hello.i
上述命令可以生成预处理之后的文件,并将之输出为Hello.i文件。

2.3 Hello的预处理结果解析
预处理结束生成了Hello.i文件,该文件长达3000行左右,即使是一个简单的Hello源文件在预处理之后也会具有很长的代码文件,这是因为在Hello文件中调用了getchar()、printf()等函数,同时包含了stdio等头文件的原因,在预处理的时候,头文件会被预处理器替换为相应的内容,同时会对#define定义的相关的宏进行展开。
如果为了方便阅读,可以在gcc的命令中添加 -C参数,他会在生成的预处理之后代码保留注释内容,方便阅读。如下。

2.4 本章小结
C语言对源程序处理的四个步骤:预处理、编译、汇编、链接。预处理是第一个环节,一般gcc并不会保留预处理产生的文件,除非显式地使用相应的命令来强制gcc生成相应地文件。除了会替换头文件外,所有用户或者是头文件中包含地宏也都会被预处理器替换,从而生成一个庞大的文件。
(第2章0.5分)

第3章 编译

3.1 编译的概念与作用
注意:这儿的编译是指从 .i 到 .s 即预处理后的文件到生成汇编语言程序
经过预处理器处理过后的文件依然并不是二进制文件,对于CPU等硬件来说,并不能识别,对于CPU来说,仅仅只有几百个指令,所以编译即是将这些语言转换为计算机所能够理解的汇编指令,从而使得硬件能够理解和执行。
编译为用户和硬件提供了一种沟通的方式。对于用户来说,使用二进制语言编程是完全不可能的,而开发者编写的c语言程序则需要通过编译才能被硬件理解,从而载入计算机中实现。编译还会检查用户提供的文件是否具有语法的错误,从而为开发提供了诸多便利。

3.2 在Ubuntu下编译的命令
(以下格式自行编排,编辑时删除)
应截图,展示编译过程!
在Ubuntu下可以使用-S命令生成已经编译但未链接的文件。gcc -S Hello.i 。
3.3 Hello的编译结果解析、
此部分是重点,说明编译器是怎么处理C语言的各个数据类型以及各类操作的。应分3.3.1~ 3.3.x等按照类型和操作进行分析,只要hello.s中出现的属于大作业PPT中P4给出的参考C数据与操作,都应解析。
所有以.开头的字符都不属于需要执行的命令,这些是指导汇编器和编译器工作的伪指令。这些指令也可以帮助我们理解程序的一些基本信息。
.file 文件名
.text 代码段
.rodata 只读数据段
.align 数据对其
.string **字符串
.global **全局变量
.type 标记符号

3.3.1 数据
  • 字符串
可以看到,对于常量字符串,它们存储在只读数据段中,并且在需要使用的时候,通过leaq指令加载进入寄存器中。

2.局部变量
对于局部变量,存储在rbp-4的地址位置,根据《CS:APP》所讲,如果程序的寄存器有空余,一般会将常用的局部变量放入寄存器中,从而加快程序运行速度,如果没有,那么局部变量就会被放入栈中。

3.数组
数组作为main函数的第二个参数,数组的首地址存储在rsi寄存器中,在后续使用rsi寄存器时,将该数组的首地址存储在了rbp-32的位置,后续使用也会引用该地址。

4.立即数
通过在前面加上$符号来表示立即数。

3.3.2 函数的调用和返回
函数的调用通过call和ret来实现,在执行call函数命令之前,所有的函数参数都必须已经通过寄存器或者是栈的方式进行传递。

3.3.3 各类常用操作
  • 赋值操作
赋值操作通过mov类函数实现,mov操作需要指定数据的大小,分别使用b,w,l,q代表单、双、四、八字节的数据。

2.算术操作
具有add、sub、mul、div等算术操作指令,算术操作同样需要指定数据大小,并且在需要的时候会进行数据转换。

3.控制转移

3.4 本章小结
本章总结了编译的目的和作用,同时分析了各个指令的操作和用法,并给出了相应的截图。
(第3章2分)

第4章 汇编

4.1 汇编的概念与作用
(以下格式自行编排,编辑时删除)
注意:这儿的汇编是指从 .s 到 .o 即编译后的文件到生成机器语言二进制程序的过程。
汇编的概念:汇编是指汇编器(as)将.s文件翻译成机器语言指令,并把这些指令打包成可重定位目标程序的格式,并将结果保存在.o文件中的过程。其中.o文件是一个二进制文件,包含程序代码和数据的机器指令编码。
汇编的作用:将.s文件中的汇编指令翻译成对应的二进制机器指令,汇编生成的可重定位目标文件可以与其他可重定位目标文件链接,形成一个可执行目标文件。

4.2 在Ubuntu下汇编的命令
使用gcc -c Hello.s 文件可以生成汇编之后的文件,这个文件是二进制文件,无法直接阅读。可以使用objdump工具反汇编之后阅读。

4.3 可重定位目标elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
elf头是位于elf文件的头部,里面存储着一些机器和该ELF文件的基本信息。其中包含端绪、机器类型、文件类型、负数描述方式等。
使用readelf -S 可以获得ELF文件的节头部表(section head table),描述了各节的名称、类型、地址、偏移量、大小、对齐要求等信息。
重定位节(relocation section):一个.text 节中位置的列表,当链接器把这个目标文件和其他文件组合时,需要修改这些位置。节中的8个重定位条目分别是对.L0、puts 函数、exit 函数、.L1、printf 函数、 sleepsecs、sleep函数、getchar 函数重定位信息的描述。其中各项的含义如下:
偏移量Offset 需要被修改的引用的节偏移。
符号名称Symbol 标识被修改引用应该指向的符号。
类型Type 告知链接器如何修改新的引用
加数Addend 一个有符号常数,一些类型的重定位需使用它对被修改引用的值做偏移调整。
(引用自百科)
符号表(symbol table):存放在程序中定义和引用的函数和全局变量的信息。链接器进行重定位需要引用的符号都在其中**。各项含义如下:
name 字符串表中的字节偏移,指向符号的以null结尾的字符串名称。
value 对于可重定位目标模块,是距定义目标的节的起始位置偏移,对于可执行目标文件,该值是一个绝对运行的地址。
size 目标的大小(以字节为单位)。
type 通常要么是数据要么是函数
Bind 字段表明符号是本地的还是全局的
(引用自百科)

4.4 Hello.o的结果解析

objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
说明机器语言的构成,与汇编语言的映射关系。特别是机器语言中的操作数与汇编语言不一致,特别是分支转移函数调用等。
反汇编之后的指令和gcc生成的指令几乎完全一致,反汇编生成的文件对于每个指令都给出了操作数。机器语言和汇编指令是一一对应的,每个指令都对应着独特的操作数(即机器语言)。

(1)条件转移
反汇编生成的文件用确定的地址,hello.s用段符号如L1、L2。

(2)函数调用
.s文件中函数调用直接接函数名称,反汇编文件中call后是调用函数的首地址。

4.5 本章小结
本章介绍了ELF文件的格式,并使用readelf工具对于ELF文件的各个部分进行了介绍,最后使用反汇编工具objdump生成反汇编文件,并于gcc生成的文件进行了对比。
(第4章1分)

第5章 链接
5.1 链接的概念与作用
注意:这儿的链接是指从 hello.o 到hello生成过程。
链接是将各种代码和数据片段收集并组合成一个单一文件的过程,源文件最终通过链接器形成可以直接被加载进入机器的二进制文件。链接可以分为静态链接和动态链接,前者在编译时进行链接,后者则可以在加载进入内存,甚至执行的时候进行链接。

5.2 在Ubuntu下链接的命令
(以下格式自行编排,编辑时删除)
使用ld的链接命令,应截图,展示汇编过程! 注意不只连接hello.o文件
可执行目标文件hello的格式
ld -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 /usr/lib/gcc/x86_64-linux-gnu/9/crtbegin.o Hello.o -lc /usr/lib/gcc/x86_64-linux-gnu/9/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o -z relro -o Hello.out
分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。
生成Hello.out文件
使用和第四章相同的命令可以得到各段的基本信息。
可以看见文件的类型变为了可执行文件(EXEC)。
使用-l参数可以查看程序头部表,他标出了程序的诸多基本信息,包括访问权限、虚拟地址等等。
使用-S参数可以查看节头部表,其中包含了各个节的对其信息、名称、大小、地址等信息。
重定位节包含每个节的偏移量等一系列信息。

5.4 hello的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。
由5.3节可以看见程序从0x404018开始,观察edb可以验证这个结果的正确性。
上述时各个地址空间区域,可以得到相关的权限、栈、堆的地址。

5.5 链接的重定位过程分析
(以下格式自行编排,编辑时删除)
objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
1.和hello.o进行对比,可以发现:hello.o中是从0地址开始的,而hello是从0x40100开始的,也就表明hello是已经重定位完成。
2.Hello程序中加入了许多新的代码,例如init程序代码,puts代码都被加入进来。
3.对于函数跳转,hello中给出了函数的首地址,而hello.o仅仅给出函数名。这表明每一个函数都已经被载入,从而拥有虚拟地址。

5.6 hello的执行流程
(以下格式自行编排,编辑时删除)
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。
0x0000000000400488 _init
0x00000000004004b0 puts@plt
0x00000000004004c0 printf@plt
0x00000000004004d0 getchar@plt
0x00000000004004e0 exit@plt
0x00000000004004f0 sleep@plt
0x0000000000400500 main
0x0000000000400590 _start
0x00000000004005c0 _dl_relocate_static_pie
0x00000000004005d0 __libc_csu_init
0x0000000000400640 __libc_csu_fini
0x0000000000400644 _fini

5.7 Hello的动态链接分析
(以下格式自行编排,编辑时删除)
分析hello程序的动态链接项目,通过edb调试,分析在dl_init前后,这些项目的内容变化。要截图标识说明。
使用readelf定位.got位置。假设程序调用了共享库里的函数,编译器无法其运行时地址,为了能使得代码段里对数据及函数的引用与具体地址无关,链接器采用延迟绑定的策略。延迟绑定是通过全局偏移量表(GOT)和过程链接表(PLT)之间的交行实现的。如果一个目标模块调用定义在共享库中的任何函数,那么它就有自己的GOT和PLT。GOT是数据段的一部分,PLT是代码段的一部分。

5.8 本章小结
本章主要介绍了链接的概念和作用,并使用readelf工具对可执行文件的各个部分、链接的过程、程序执行的流程进行了介绍。
(第5章1分)

第6章 hello进程管理

6.1 进程的概念与作用
(以下格式自行编排,编辑时删除)
进程的概念:执行中的程序的实例,系统总每个程序都影星在某个进程的上下文中。上下文由程序运行所需的状态组成。这些状态包含代码、数据块、环境变量等。
进程的作用:提供一个程序独占的使用处理器和内存的假象,程序员在设计程序的时候可以假定程序时当前系统中唯一运行的程序。

6.2 简述壳Shell-bash的作用与处理流程
作用:它主要是一个可以和用户进行交互的应用程序,可以解释用户的输入命令,并执行其他的应用程序。
处理流程:
1.用户通过键盘或者其他形式(文件)输入命令
2.Shell程序解析命令,并存入argv数组中
3.Shell判断是否为内置命令,如果是,直接执行相应的函数,否则将参数看作一个可执行程序的路径,调用fork创建子进程,并使用execve执行程序。
4.如果该命令为前台命令,则程序等待命令执行完成后才等待用户输入,否者程序将后台执行,并等待用户输入。

6.3 Hello的fork进程创建过程
(以下格式自行编排,编辑时删除)
当用户按照Hello程序正确键入参数后,shell就会使用fork创建一个新的子进程。新创建的子进程几乎但不完全与父进程相同,子进程得到与父进程虚拟地址空间相同但独立的一份副本,包括代码段、数据段、共享库以及用户栈。子进程还获得与父进程打开文件描述符相同的一份副本,父进程和子进程的根本不同在于他们的PID。父进程与子进程是并发运行的独立进程,内核能够以任意方式交替执行它们的逻辑控制流的指令。

6.4 Hello的execve过程
fork 创建子进程之后,子进程调用execve 函数在当前进程的上下文中加载并运行 一个新程序hello。新程序会覆盖覆盖当前进程的代码、数据、栈,但拥有和当前进程相同的PID,并继承已打开的文件描述符、进程上下文和信号阻塞状态。execve函数加载并运行可执行目标文件hello,创建一组新的代码、数据、堆和栈段,设置PC 指向_start 的地址,调用main函数,并将控制传递给新程序的主函数,同时传递参数列表argv和环境变量envp。只用当发生错误时,execve函数才会用返回值,否则永不返回。

6.5 Hello的进程执行
(以下格式自行编排,编辑时删除)
结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换等等。
上下文信息:就是进程被执行所需要各类信息,包含寄存器值、用户栈、内核栈等各种硬件和软件信息
进程时间片:一个进程执行它的控制流的一部分的每一时间段叫做时间片。
进程调度:当内核选择一个新的进程运行时,称内核调度了这个进程。在内核调度了一个新的进程运行后,它就抢占当前进程,并使用一种称为上下文切换的机制来将控制转移到新的进程,上下文切换包含:
  • 保存当前进程的上下文
  • 恢复某个先前被抢占的进程被保存的上下文
  • 将控制传递给这个新恢复的进程。
    Hello通过Shell载入之后,一直在用户模式运行(其中可能会由进程切换),其中当遇到系统函数时候,会切换为内核模式,执行相应的命令之后,切换回用户模式,直到运行sleep函数,控制将用户移交给内核,内核将进程挂起,当sleep设定的时间结束之后,定时器发送一个信号,内核接受信号并执行信号处理程序,Hello程序重新进入待执行状态。
    6.6 hello的异常与信号处理
    (以下格式自行编排,编辑时删除)
    hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
    程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
  • 可能会产生中断、陷阱和故障三种异常。
    1.异常。Hello程序在运行过程中可能会产生来自I/O设备的信号而导致的中断。
    2.陷阱。程序执行系统调用,例如sleep、exit时候,会通过陷阱将控制权转交给内核,内核执行相应的命令之后,将控制返回到下一条命令。
    3.故障。程序在执行的时候,可能会从硬盘中读取数据(或者长时间等待用户输入),这个时候可能会引发缺页故障。

正常运行程序,程序在每个参数指定的秒数之后,打印出相应的内容。、
5.
在程序执行的过程中,通过按Ctr-Z,会向当前运行的前台进程组发送SIGTSTP信号,信号处理程序暂停了该程序,并打印出相应的信息,这个时候运行ps
可以看见Hello程序仍在进程组中
输入jobs命令可以看见,Hello进程的状态为stopped。
这个时候,既可以使用kill函数,终止Hello函数的运行,也可以使用fg函数将该进程继续加载到前台运行。、
在程序运行过程中乱按键盘不会对程序产生影响,这些被键入的字符会被缓存到stdin中,如果程序需要从stdin中读取数据,那么就会读取到相应的字符。


6.7本章小结
本章主要介绍了进程的概念、作用和创建流程,并通过Hello程序为例,给出了进程切换的过程和相应的异常处理。
(第6章1分)

第7章 hello的存储管理

7.1 hello的存储器地址空间
(以下格式自行编排,编辑时删除)
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
逻辑地址:在有地址变换功能的计算机中,访存指令给出的地址 (操作数) 叫逻辑地址,也叫相对地址。要经过寻址方式的计算或变换才得到内存中的实际有效地址,即物理地址。
线性地址:线性地址是逻辑地址到物理地址变换之间的中间层。程序代码会产生逻辑地址,或者说是段中的偏移地址,加上相应段的基地址就生成了一个线性地址。
虚拟地址:即线性地址。
物理地址:物理地址用于内存芯片级的单元寻址,CPU对内存的访问是通过连接着CPU和北桥芯片的前端总线来完成的(目前大部分个人电脑已经不存在独立的北桥芯片,它被嵌入到CPU中,从而提高传输速率)。在前端总线上传输的内存地址都是物理内存地址。

7.2 Intel逻辑地址到线性地址的变换-段式管理
首先,给定一个完整的逻辑地址[段选择符:段内偏移地址],
1.看段选择符等于0还是1,判断当前要转换是GDT中的段还是LDT中的段,再根据相应寄存器,得到其地址和大小。
2.拿出段选择符中前13位,可以数组中查找到对应的段描述符,就可以得到段基地址
3.将基地址和段偏移地址相加,就是要转换的线性地址。

7.3 Hello的线性地址到物理地址的变换-页式管理
为了提高空间局部性,虚拟内存和物理内存都被分为虚拟页(VP)和物理页(PP),系统使用页表来管理从虚拟页到物理页的映射。每个虚拟地址由虚拟页号和虚拟页偏移量组成。如果设置有效位说明该页已缓存到物理内存,缓存命中,直接返回PTE,MMU从而构建物理地址,并发送给缓存。
CPU通过MMU将虚拟地址翻译成物理地址,通过VPN找到对应的页表条目,如果不命中,发生缺页故障,与页面命中不同,缺页故障需要硬件和操作系统共同处理。此时MMU会选择一个牺牲页(这个选择由缺页处理程序来进行选择,不同操作系统可能会采用不同的替换策略),用将产生缺页的虚拟页替换牺牲页,并更新页表,然后重新执行导致缺页的指令。

6.4 TLB与四级页表支持下的VA到PA的变换
对于每个虚拟地址,MMU都必须查询PTE,从而潜在的可能访问内存,降低效率,从而设计出TLB来降低不命中的概率。TLB是一个小的、虚拟寻址的缓存,MMU在翻译时会首先从TLB中查找是否存在相应的PTE,如果没有就会从L1缓存中取出相应的PTE,并更新TLB,如果有就会直接返回相应的PTE。多级页表的设计是为了减小内存的压力,如果有大量的PTE需要存储,就会占用大量空间,多级页表利用每上一级页表作为下一级页表的索引来减小主存压力,因为这时只有一级页表和最常使用的二级页表才会缓存在主存中。
虚拟地址到物理地址的翻译需要确定PTE,而TLB的设计就是利用空间局部性来加快PTE的查询。MMU会首先在一级页表中查询PTE,如果为空,就是直接跳过,按照之前的方式查询PTE,否则会逐渐二级、三级、四级查询PTE,最终找到相应的PTE,同时,在未能找到PTE时会更新TLB。

7.5 三级Cache支持下的物理内存访问
存储器层次结构的中心思想是:对于第k层的更小更快的存储器设备作为位于k+1层更大更慢的存储设备的缓存。所以三级Cache内存访问都是十分类似的:
1.组选择。通过虚拟地址的组索引,找到相应的组
2.行匹配。将虚拟地址除去索引部分,和组内所有的块进行比较,如果匹配成功,并且有效位为1,这缓存命中,否则缓存不命中。
3.(1)缓存命中。一旦缓存命中,根据偏移位即可取出相应的字节并传输给CPU。(2)缓存不命中。需要向下一级缓存寻找相应的地址,并且替换掉行中原有的块。不同的缓存具有不同的替换策略。
L2,L3的内存访问过程类似,不过有些不同的是,随着缓存空间越大,速度越低,替换和查询的策略有所不同,越往下越倾向于使用写回以及更复杂的替换策略。

7.6 hello进程fork时的内存映射
当fork函数被当前进程调用时,内核为新进程创建各种数据结构,并分配给它一个唯一的PID。为了给这个新进程创建虚拟内存,它创建了当前进程的mm_struct、区域结构和页表的原样副本。它将两个进程中的每个页面都标记为只读,并且把两个进程中的每个区域结构都标记为私有的写时复制。
——图片引自百科

7.7 hello进程的execve的内存映射
Execve函数的执行包含一下步骤:
1.删除已存在的用户区域
2.映射私有区域,为新程序的代码、数据等创建新的区域结构,都是私有的写时复制的。
3.映射共享区域,把动态链接库映射到共享区域
4.设置程序计数器(PC),使之指向代码区域的入口点。

7.8 缺页故障与缺页中断处理
当指令引用一个虚拟地址,通过查找页表发现,该虚拟地址对应的物理地址所在的物理页不在内存中,需要从磁盘调入,即发生了缺页故障。
当发生缺页故障时,控制转移到处理程序,处理程序从磁盘加载相应的页面,然后将控制转移给引起缺页故障的指令,指令重新执行,相应的物理页面已被加载到内存中


7.9动态存储分配管理
(以下格式自行编排,编辑时删除)
Printf会调用malloc,请简述动态内存管理的基本方法与策略。
动态内存内存管理由分配器进行处理,分配器维护一段虚拟内存区域,称为堆,堆向高地址方向伸展,同时由于许多数据结构要求地址空间连续(数组等),所以堆会产生许多碎片,从而降低堆的利用率。为了解决碎片问题,并对堆空间的分配、回收问题进行处理,常用的分配器采用下面三种数据结构来对堆进行维护。
1.隐式空闲链表。隐式空闲链表将未分配的空间的起始位置按照链表的形式链接,每次分配内存时查找到合适的位置,并分割出相应的空间,并更新相应的节点,释放内存时需要合并相应的节点(如果两个节点首尾相接)。
2.显式空闲链表。显式空闲链表是将空闲块组织为某种形式的显式数据结构。因为程序不需要一个空闲块的主体,所以实现这个数据结构的指针可以存放在这些空闲块的主体里面。
3.分离空闲链表。将所有可能的块大小分成一些等价类,分配器维护空闲链表的数组,每个等价类一个空闲链表,按照升序排列。

7.10本章小结
本章介绍了系统的虚拟地址和物理地址之间的工作原理,并通过fork、exevce函数介绍了内存映射的概念和工作流程。最后,介绍了动态内存分配的方法和策略。(第7章 2分)

第8章 hello的IO管理

8.1 Linux的IO设备管理方法
(以下格式自行编排,编辑时删除)
设备的模型化:文件
设备管理:unix io接口

8.2 简述Unix IO接口及其函数
(以下格式自行编排,编辑时删除)

8.3 printf的实现分析
(以下格式自行编排,编辑时删除)
https://www.cnblogs.com/pianist/p/3315801.html
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。

8.4 getchar的实现分析
(以下格式自行编排,编辑时删除)
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。

8.5本章小结
(第8章1分)
结论
用计算机系统的语言,逐条总结hello所经历的过程。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
1.将Hello.c文件传输入虚拟机,并使用vscode 打开。
2.适应cpp对Hello.c文件进行预处理,得到hello.i,gcc在处理的使用是默认不生成hello.i的预处理文件,需要显式地通过命令指定。
3.Hello.i程序经过编译可以得到相应的汇编程序hello.s
4.Hello.s经过as汇编可以得到重定位程序hello.o
5.Hello.o程序经过链接,可以得到可执行程序hello.out
6.通过shell,可以调用fork、execve函数创建子进程并将hello.out载入。从此完成了P2P的过程。
7.用户模式和内核模式交互进行,从而执行Hello程序。
8.可以通过键盘向程序发送相应的信号,使得信号处理程序接受相应的信号,并做出对应操作。
(结论0分,缺失 -1分,根据内容酌情加分)

附件
列出所有的中间产物的文件名,并予以说明起作用。
(附件0分,缺失 -1分)
参考文献
为完成本次大作业你翻阅的书籍与网站等
[1] 林来兴. 空间控制技术[M]. 北京:中国宇航出版社,1992:25-42.
[2] 辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.
[3] 赵耀东. 新时代的工业工程师[M/OL]. 台北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).
[4] 谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.
[5] KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.
[6] CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.
(参考文献0分,缺失 -1分)


版权**本文为[东风中的蒟蒻]所创,转载请带上原文链接,感谢https://blog.csdn.net/m0_50089378/article/details/124879850




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

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2024 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

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