程序人生 您所在的位置:网站首页 excel表格中锁定部分表格不让修改内容 程序人生

程序人生

2023-05-17 18:45| 来源: 网络整理| 查看: 265

 

计算机系统

大作业

题     目  程序人生-Hello’s P2P 

专       业     网络空间安全       

学     号      2021110859        

班     级      2103901           

学       生      王邦国           

指 导 教 师       吴锐             

计算机科学与技术学院

2023年5月

摘  要

摘要是论文内容的高度概括,应具有独立性和自含性,即不阅读论文的全文,就能获得必要的信息。摘要应包括本论文的目的、主要内容、方法、成果及其理论与实际意义。摘要中不宜使用公式、结构式、图表和非公知公用的符号与术语,不标注引用文献编号,同时避免将摘要写成目录式的内容介绍。

关键词:预处理;编译;汇编;链接;进程;异常;信号;IO接口;计算机系统                        

(摘要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章 概述 1.1 Hello简介

根据Hello的自白,利用计算机系统的术语,简述Hello的P2P,020的整个过程。

p2p过程

用户使用编辑器(editor)创建了一个源代码文件 hello.c,这个文件存储了hello程序的逻辑。

用户将hello.c文件进行预处理(preprocessing),生成一个新的文件,其中包含了一些机器指令、宏定义以及其他编译需要的信息。

编译器(compiler)将新生成的文件翻译为汇编代码(assembly code)。

汇编器(as)将汇编代码转化为机器码(machine code)。

链接器(ld)将程序中需要使用到的库文件链接起来,生成可执行文件(executable file)hello。

用户通过操作系统提供的命令行界面(bash),在终端中输入./hello命令运行程序。

操作系统(os)为hello进程分配内存、cpu时间片、i/o资源等,使其能够运行。

系统调用fork创建了hello进程,实现了进程间通信的隔离。

execve系统调用将hello进程替换成用户请求的可执行文件。

mmap系统调用为程序分配内存空间。

cpu执行程序,按照取指译码执行周期对指令逐步解析、执行,完成hello程序的功能。

o2o过程

编写代码,预处理,编译,汇编,链接同上。

进程管理:当用户运行"hello.exe"时,操作系统会为该进程分配资源,如内存空间和cpu时间片等等。

执行程序:当操作系统将"hello.exe"运行起来后,cpu执行该程序的机器指令,依据指令流水线(instruction pipeline)执行相关操作。

存储管理:操作系统根据虚拟地址(virtual address)映射为物理地址(physical address),通过内存管理单元(memory management unit)来实现虚拟内存(virtual memory)功能,并使用tlb、4级页表(four-level page table)、3级cache(three-level cache)、pagefile等技术加速内存访问。

io管理:在程序运行过程中,操作系统负责对外设进行管理和控制,如鼠标、键盘、屏幕等输入输出设备。

收尸:当程序执行结束时,操作系统会将该进程所占用的资源进行回收与清理。

1.2 环境与工具

列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。

软件环境:Windows11 64位;Vmware 15;Ubuntu 20.04.4 LTS 64位

硬件环境:CPU:AMD Ryzen 7 5800H 3.2GHz 15G 575G

开发与调试工具:codeblocks,edb,gcc。

1.3 中间结果

列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。

hello.i文件                预处理之后的文件

hello.s文件               编译之后的文件

hello.o文件               汇编后的可重定位目标文件

hello文件                  链接后生成的可执行文件

hello.elf文件            hello的ELF文件

helloboy.elf文件       hello.o的ELF文件

1.4 本章小结

       介绍了hello程序的p2p过程和020过程,硬件环境、软件环境和开发工具,描述了中间文件的名字和作用

(第1章0.5分)

第2章 预处理 2.1 预处理的概念与作用

程序预处理的概念与作用

预处理一般是指在程序源代码被翻译为目标代码的过程中,生成二进制代码之前的过程。

作用:

宏扩展:预处理器中的宏可以使代码重复利用更加容易,也便于修改和调整。条件编译:通过条件编译,可以根据不同的需要编译不同版本的代码,实现跨平台等功能。头文件包含:头文件可以定义常量、变量、函数及结构体等,通过包含头文件,可以方便的使用这些声明。注释的清除:注释虽然对阅读者很有帮助,但对编译器并没有什么意义,因此程序预处理可以去掉注释,减小目标代码的大小。预处理指令的扩展:预处理指令可以比c语言更强大和灵活,在处理时会被扩展成普通的c代码。

2.2在Ubuntu下预处理的命令

在终端下输入指令:gcc -E -o hello.i hello.c,会发现当前文件夹下生成了hello

 

图2.1.预处理指令

2.3 Hello的预处理结果解析

编译器对"hello.c"文件进行预处理,将包含在代码中的其他头文件(header file)复制到该文件中,并做一些相关处理。可以看到.i文件中开始包括了很多的.h文件的地址。

              最终找到所有的文件存到一起,就是多出来的3000多行的代码。

 

 

图2.2.1.预处理结果

代码的末尾部分是.c文件中的内容,相当于接到了3000多行代码的末尾,最后整合形成了hello.i文件

 

 

图2.2.2.图预处理结果

2.4 本章小结

预处理初步翻译源文件,进行宏替换,文件包含,删除注释等操作,熟悉了Ubuntu下预处理的命令,解析了hello.c预处理的结果。

(第2章0.5分)

第3章 编译 3.1 编译的概念与作用

概念:编译是将已经预处理好的C语言源代码(hello.i文件)翻译成汇编语言(hello.s文件)的过程。

预处理完成后,编译器会利用目标架构的指令集将c/c++程序源代码编译成汇编语言程序。这个阶段应当生成包含机器码的文本,以便运行该程序。

因此,编译的目的是使计算机能够理解人类使用的自然语言所写的代码。最终的输出文件.s会被汇编器进一步处理为二进制机器码。

过语法分析和词法分析,在确认所有的指令都符合语法规则后,将预处理程序翻译成等价的中间代码表示或汇编代码

  

3.2 在Ubuntu下编译的命令

在终端处输入指令:gcc -S hello.i -o hello.o,会发现文件夹中生成了hello.s文件,如图所示:

 

 

图3.1.编译指令

3.3 Hello的编译结果解析 首部

.file:文件名

.text:指示接下来将会定义程序的代码 section

.section .rodata:只读数据段,即字符串常量可以存储在该段内

.align 8:强制对齐到 8 个字节

.globl main:标记了 main 函数为全局函数

.type main, @function:将 main 函数标记为函数类型

 

图3.2.1.hello编译结果解析

字符串:

编译器将字符串字面值转换为对应的ASCII码值序列,并将其储存在只读数据段(.rodata)中。在LC0中,编译器将中文字符的UTF-8编码转换为相应的ASCII码序列,以便程序正确处理中文编码。在LC1中,字符串被格式化为包含两个%s的字符串,因此编译器在生成可执行文件时会分配足够的内存来存储这些字符串。在程序运行时,这些字符串会被读取并传递给相应的printf函数。

 

图3.2.2.hello编译结果解析

数字常量:

数字常量被直接编码为32位或64位的二进制整数,它们的值与原代码中的字面值相同。例如,$4、$1和$0分别表示整数4、1和0。这些常量会被直接加载到寄存器中,与其他操作数一起参与特定的指令执行。因此,编译器只需要简单地将数字常量转换为相应的二进制表示,并嵌入到程序的机器码中。

比如对应c语言for(i=0;ihello.txt反汇编代码并打开

 

 

图5.9.反汇编指令

不同点:

代码的行数增加了许多。hello_o.txt中只有main程序的代码,但是hello.txt中包含了所有此程序需要用到的代码,包括引用的函数。原来调用的C标准库中的代码都被插入了代码中,并且经过了链接之后给每个函数都分配了各自的虚拟地址,如图

 

 

图5.9.增加的函数

3.hello中发现所有的地址均为相对地址,是相对于main函数的地址,而在hello.txt中可以发现已经给各个代码分配了虚拟地址,如图

 

 

图5.10.hello.txt地址示例

同时也发现hello.s中对于函数的调用原来也是使用的偏移地址的方法2f,而在hello.txt中调用的函数位置为虚拟地址0x4010d0不再使用相对位置。跳转指令也是同样的原理。

重定位过程:

首先重定位节和符号定义,连接器将所有相同类型的节合并为同一类型的新的节,然后将运行内存地址赋给这个新的节和输入模块定义的每个节以及输入模块定义的每个符号;然后依靠连接器修改代码节和数据节中对每个符号的引用,使之指向正确的运行地址。

objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。

结合hello.o的重定位项目,分析hello中对其怎么重定位的。

5.6 hello的执行流程

使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。

流程: 开始执行:_start, _libc_start_main

执行mian:_main, _printf, _exit, _sleep, _getchar

退出:exit

 

图5.11.hello调用的各个子程序和程序地址

 

使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。

5.7 Hello的动态链接分析

   在进行动态链接前,首先进行静态链接,生成部分链接的可执行目标文件hello。此时共享库中的代码和数据没有被合并到hello中。加载hello时,动态链接器对共享目标文件中的相应模块内的代码和数据进行重定位,加载共享库,生成完全链接的可执行目标文件。

动态链接采用了延迟加载的策略,即在调用函数时才进行符号的映射。使用偏移量表GOT+过程链接表PLT实现函数的动态链接。GOT中存放函数目标地址,为每个全局函数创建一个副本函数,并将对函数的调用转换成对副本函数调用。

由hello的elf文件可知,got表是0x403ff0为首地址

 

 

图5.12.elf文件中.got节和.got.plt节

在dl_init之前:

 

 

图5.13.dl_init之前

在dl_init之后:

 

 

图5.14.dl_init之后

通过这两者前后的对比可以看出: 最初地址的字节都为0,调用_init函数之后got内容产生变化,指向正确的内存地址,以便下一次调用跳转时可以跳转到正确位置。

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

5.8 本章小结

简单概括链接的概念和作用,并且详细阐述了hello.o文件是怎么链接成为一个可执行目标文件的过程。也介绍了hello.o的ELF格式和各个节的含义,并分析hello的虚拟地址空间、重定位、执行流程、动态链接这几个过程的原理。

(第5章1分)

第6章 hello进程管理 6.1 进程的概念与作用

进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。

作用:

进程是计算机科学中最深刻、最成功的概念之一。它令我们得到一种假象:我们的程序好像是系统中当前运行的唯一的程序一样;我们的程序好像是独占地使用处理器和内存;处理器好像是不间断地执行着指令;我们程序中的代码和数据好像是系统内存中唯一的对象。

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

作用:

shell是一个高级程序设计语言编写的程序,它是用户使用linux的桥梁。它既是一种应用,也是一种程序设计语言。这种应用程序提供了一个界面,用户通过这个界面访问操作系统的内核服务。

处理流程:

1.从终端读入输入的命令

2.将输入的字符串切分从而获得所有的参数

3.如果命令为内置命令则立刻执行,否则调用相应程序为其分配子进程并运行

4.Shell会随时接收键盘传来的信号并对其处理

6.3 Hello的fork进程创建过程

终端程序通过调用fork()函数创建一个子进程,子进程得到与父进程完全相同但是独立的一个副本,包括代码段、段、数据段、共享库以及用户栈。子进程还获得与父进程任何打开文件描述符相同的副本,父进程和子进程最大的不同时他们的PID是不同的。父进程与子进程是并发运行的独立进程,内核能够以任意方式交替执行它们的逻辑控制流的指令。在子进程执行期间,父进程默认选项是显示等待子进程的完成。

以我们的hello为例,当我们输入 ./hello 2021110859 王邦国 1的时候,首先shell对我们输入的命令进行解析,由于我们输入的命令不是一个内置的shell命令,因此shell会调用fork()创建一个子进程,如图:

 

 

图6.1.示例

6.4 Hello的execve过程

(execve函数在当前进程的上下文中加载并运行一个新程序。函数声明如下:

int execve(const char *filename, const char *argv[], const char *envp[]);

execve函数加载并运行可执行目标文件filename,且带参数列表argv和环境变量列表envp。只有当出现错误时,例如找不到filename,execve才会返回到调用程序。正常情况下,execve调用一次,但从不返回。

创建新进程后在新进程中调用execve函数会在当前进程中加载并运行包含在可执行文件hello.out中的程序,加载并运行hello.out需要以下几个步骤。第一步,删除已存在的用户区域,即删除当前进程虚拟地址的用户部分中的已存在的区域结构。第二步,映射私有区域,为新程序的diamante,数据,bss和栈区域创建新的区域结构,这些新的区域均为私有的,写时复制的。第三步,映射共享区域,即与hello.out链接的共享对象(如标准C库libc.so),它们都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。第四步,设置程序计数器(PC),设置当前进程上下文中的程序计数器,使之指向代码区域的入口点。经过这样几步,execve函数就完成了hello.out这个可执行程序的加载。

6.5 Hello的进程执行

进程调度是操作系统中非常重要的一部分,它负责为多个进程在cpu上分配时间片,保证每个进程都可以得到公平的cpu执行时间。下面是关于进程调度过程及用户态与核心态转换的一些说明:

进程调度过程

当有新的可运行进程时,操作系统会根据规定的算法从就绪队列中选取一个最优进程,并将处理器的控制权交给该进程。

进程调度可以分为三个阶段:进程切换、上下文恢复和用户态/核心态的转换。这三个阶段之间没有明确的界限,它们通常是同时进行的,并在某些情况下可以通过优化来合并成一个步骤。

进程切换:当操作系统决定让另一个进程使用cpu时,首先要切换到该进程的上下文。这包括保存当前进程的寄存器状态、堆栈指针以及程序计数器等信息,并还原或者更新被调入进程保存的上下文。

上下文恢复:一旦目标进程的上下文切换完成,操作系统会开始执行上下文恢复操作,这意味着它会将寄存器和内存变量的值设置为正确的副本,复位再重新启动新进程被中止执行时计数器的值,以确保进程从正确位置开始执行。

用户态/核心态转换:当进程切换到内核模式时,它需要进行用户态和核心态之间的转换。在用户态中运行的程序只能使用有限的系统资源,如存储器、cpu时间片等,而内核态则具有更高的权限,因此可以直接访问计算机的所有系统资源

结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换等等。

6.6 hello的异常与信号处理

正常情况:

       正常情况下,SHELL输出N次信息后等待用户随意输入一条指令然后终止程序

 

 

图6.2.正常情况

Ctrl+C和Ctrl+Z:

当在hello输出过程中从键盘输出CRTL-C和CRTL-Z时,程序会被终止和挂起,这是由于这些键盘输入会给父进程发送一条信号,这条信号会使该进程调用信号处理程序。导致在本例中,输入Ctrl-C(Ctrl-Z)的结果就是内核会发送一个

SIGINT(SIGSTP)信号给前台进程组中的每个进程,使他们被强制终止(被挂起)。

 

 

图6.3.1ctrl+c

 

 

图6.3.2.ctrl+z

输入PS:

       输入ps,可以查看当前所有进程的相关信息,可以发现此时hello程序仍然存在

 

 

图6.4.ps

输入jobs:

       输入jobs可以查看前台作业号

 

 

图6.5.jobs

输入pstree:

       输入pstree命令,以树形结构显示了程序和进程间的关系。

 

 

图6.6.1.pstree

 

 

图6.6.2.pstree

输入fg:

输入fg,能使被挂起的hello程序变成前台程序继续运行。

 

 

图6.7.fg

输入kill:

       输入kill命令:杀死这个停止的进程(产生SIGKILL信号)

 

 

图6.8.kill

hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。

 程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps  jobs  pstree  fg  kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。

6.7本章小结

本章主要讲述了hello.out这个程序的进程管理,首先系统会创建一个新进程,在新进程中加载和调用hello.out这个可执行程序,在执行hello.out的过程中涉及到并发流,切换进程工作模式,进行上下文切换,这些操作是为了提高系统整体的效率并保护系统的安全。同时有一套异常处理机制来处理各种异常,包括系统有意为之,程序中出现的调用和出现某些错误,这样的一套异常处理机制保证了hello.out能完成运行,能切换到内核模式再切换回来,并且保证内核不会因为某些错误卡死。

(第6章1分)

第7章 hello的存储管理 7.1 hello的存储器地址空间

"hello"程序在内存中存储的位置会涉及四个地址概念:逻辑地址、线性地址、虚拟地址和物理地址。

逻辑地址是应用程序发出的一个地址,通常由cpu生成。这个地址是相对于该进程自己的确切起始位置而言的。它不会改变物理地址,仅描述进程如何访问其内部内存。例如,当一个程序要读取数据时,它只需要发出逻辑地址即可,而无需真正了解这些数据在物理内存中的具体位置。

线性地址是从0x00000000到0xffffffff的一段连续的地址空间,在操作系统看来应当是从逻辑地址透明映射而来,或者经由硬件地址转换簿进行转换后得到的;

虚拟地址(也称逻辑地址)是在进程视角下的地址空间,它由进程自己定义,这些地址可能会被映射到线性地址或物理地址上。操作系统可以根据进程的需要来为每个进程分配相应的虚拟地址空间,让它们可以互不干扰地运行。

物理地址是实际存在于ram(或其他存储设备)中的物理内存地址。当操作系统需要将cpu发出的逻辑地址映射到真实的物理地址时,它会对线性地址进行转换(如果需要的话),并将其映射到对应的物理地址上。

因此,在hello这个例子中,逻辑地址是由程序使用的抽象地址,用于访问它自己进程内部的内存;线性地址是操作系统向进程提供的虚拟地址空间,每个进程都有自己独立的线性地址空间;虚拟地址是进程视角下的地址空间,由进程自己定义,可能会被映射到线性地址或物理地址上;物理地址是实际存在于ram中的物理内存地址。当cpu需要读取hello程序中的数据时,它会发出逻辑地址,操作系统在向进程提供的线性地址空间和进程页表中进行查找,并将其转换为对应的物理地址,然后cpu才能访问这些数据。

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

段式管理是一种内存地址变换的方式,将逻辑地址转换为线性地址。使用段式管理需要使用一组描述内存分区的段描述符,每个段描述符包含了段的起始物理地址、段的长度以及一些控制位等信息。

从逻辑地址中获取段选择子(16位)。段选择子指定了要访问的段描述符在全局描述符表(gdt)或局部描述符表(ldt)中的索引。

根据段选择子定位到对应的段描述符,并将其加载入gdtr或ldtr中。

从逻辑地址中获取段内偏移量。段内偏移量指定了相对于段起始地址的偏移量。

将段描述符中的基地址和段内偏移量相加,得到线性地址。

 

 

图7.1.段式管理

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

在页式管理下,将一个程序的逻辑空间(虚拟地址)分为大小固定的块,即页,使得实际的物理内存分配也是按页进行的。这种访问方式可以提高内存利用率,减少外部碎片,并且易于动态调整页面大小。

将线性地址分解为页目录表索引、页表索引和页内偏移量。页目录表和页表都是由操作系统维护的数据结构,用来记录虚拟空间中每个页对应的物理地址或其他相关信息。

使用页目录表中索引所指向的页表基址,找到页表项,并使用页表索引所指向的页帧号码(对应实际物理内存中的一块空闲区域)、标志等信息,计算出虚拟地址对应的物理地址。

将页帧号和页内偏移量组合成最终输出的物理地址。

 

 

图7.2.页式管理

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

cpu生成一个虚拟地址(va),包括一个页号(pn)和偏移量(offset)。例如:va = 0x12345678

cpu查找tlb以查看是否有相应的页表项(pti)。如果未命中,则跳转到步骤3;如果已命中,则使用物理页帧号(pfn)从页表项(pte)得到物理地址(pa)。然后将偏移量添加到pa以获得最终的物理地址。例如: pa = pfn + offset

如果tlb未命中,则cpu需要使用页表来确定物理地址(pa)。首先,cpu从pn获取四级页表的索引,然后使用该索引查找第一级页表,以获取指向第二级页表的地址。

然后cpu使用第二级页表索引的值查找第二级页表,并重复这个过程直到第四级页表得到。

在第四级页表中,cpu使用offset作为索引来查找页框号(pfn)。

最终的物理地址(pa)是pfn和偏移量(offset)的组合。例如: pa = pfn + offset

需要注意的是,如果在本次va到pa变换过程中使用的页表项(pti)不在tlb中,则可能会触发一个缺页异常,导致cpu需要访问磁盘进行页面调入操作。

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

cpu发出请求:当cpu需要读取或写入内存中的数据时,首先会向l1 cache发送请求。如果所需的数据在l1 cache中已经存在,则可以直接从l1 cache中获取;否则,请求将传递到下一级缓存。

请求到达l2 cache:如果l1 cache无法找到所需数据,则请求将传递到l2 cache。通常情况下,l2 cache也比l1 cache更大,因此它具有更高的查找概率。

请求到达l3 cache:如果l2 cache也无法找到所需数据,则请求将传递到l3 cache。l3 cache通常比l2 cache更大,但速度较慢。

请求到达内存控制器:如果l3 cache都无法找到数据,则请求将传递到内存控制器。内存控制器是负责管理整个系统内存的专用硬件。

数据从物理内存返回:一旦内存控制器找到所需的数据,它将返回给cpu,并存储到l1 cache中以供后续使用。同样,在这个过程中,如果数据无法在某个缓存层中找到,则会向上一级缓存或内存控制器进行请求。

7.6 hello进程fork时的内存映射

当一个进程执行fork()系统调用创建子进程时,子进程会获得和父进程一样的代码、数据和堆栈空间的副本。在这个过程中,内核将为子进程新分配一块虚拟地址空间,并将该空间映射到与父进程相同内容的物理页面上。

具体来说,当fork()函数被调用时,操作系统会创建子进程的进程描述符和页表等数据结构,并将其与父进程的相应结构复制,以确保子进程与父进程之间的隔离性。接着,内核会依次对每个页表项进行处理,以创建子进程的页表并将其映射到相应的物理页面。

值得注意的是,在写时复制(copy-on-write,cow)技术的支持下,内核只会将子进程的虚拟地址空间映射到父进程所使用的物理页面上,并且只有在需要修改其中某个页面时才会创建一个新的物理页面并将其映射到子进程的地址空间,避免在fork()时昂贵的内存开销和复制时间消耗。

7.7 hello进程execve时的内存映射

在进程中调用 execve() 函数时,当前的进程映像会被新程序的映像替换。这个过程可以分为以下步骤:

将新程序读入内存。

创建并初始化一个新的程序堆栈(包括命令行参数和环境变量)。

关闭所有旧程序打开的文件描述符,并根据需要重定向标准输入、输出和错误。 释放旧程序使用的所有资源。

新程序开始执行。

在新程序读入内存时,在进程空间中将会创建一个新的虚拟内存空间。这些虚拟地址空间将与磁盘上的可执行文件或共享库中的代码段、数据段和堆栈段相关联。

当进程开始执行新程序时,虚拟地址空间映射到实际的物理内存页。这个过程通过页面调度算法完成,每个进程都有一个自己的地址空间。

在可执行文件和共享库中可执行代码部分是只读的和可执行的,所以它们被映射到虚拟地址空间的文本段。数据段(静态数据和全局变量)和堆(动态分配的内存)也被映射到虚拟地址空间的可写数据段,而堆栈会成为特殊的地方,此处用于函数调用,以在程序运行时动态地分配内存。共享库中的符号被映射到虚拟空间的位置的代码段。

总之,在一个进程中,新程序的映像将会替代旧程序的映像,并被映射到虚拟地址空间中。每个映射都与可执行文件或共享库中的代码、数据和堆栈相关联,并且会通过页面调度算法将虚拟地址空间映射到实际的物理内存页。这个过程中还会创建并初始化一个新的程序堆栈,包括命令行参数和环境变量,并根据需要关闭所有旧程序打开的文件描述符,并进行标准输入、输出和错误的重定向。旧程序使用的所有资源也将被释放,使新程序可以开始执行。新程序中可执行代码部分被映射到文本段,数据段和堆被映射到可写数据段,共享库中的符号则被映射到代码段。在全部替换完成后, 进程现在就运行着全新的程序映像了。

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

缺页故障

缺页故障是操作系统中的一种错误,当程序需要访问某个虚拟内存页时,该页不在内存中可用时就会发生缺页故障。在这种情况下,操作系统需要从磁盘中读取所需的页面,并更新页面表,以便将其分配到物理内存中。

缺页中断处理

当缺页故障出现时,cpu 会向操作系统发送一个中断请求,这称为缺页中断。缺页中断处理程序是操作系统中的一部分,它负责响应缺页中断并执行必要的操作,包括:

通过磁盘 i/o 读取缺失的页面;

更新页表,以便将新页面映射到正确的虚拟地址;

将页面加载到物理内存中,使其可供进程使用;

恢复产生中断的指令,使进程能够继续执行。

缺页中断处理程序是操作系统中非常重要的一部分,因为它对系统性能和响应时间有很大的影响。优化中断处理程序可以减少系统的延迟并提高效率。

7.9动态存储分配管理

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

Printf会调用malloc,请简述动态内存管理的基本方法与策略。

7.10本章小结

本章阐述了计算机中虚拟内存管理,物理地址,线性地址,逻辑地址的区别以及他们的变换模式。描述了段式和页式管理,了解了内存映射,以及在此基础上认识共享对象,fork和execve。同时学到了动态储存分配的方法和原理。

(第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所经历的过程。

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

Hello.c经过预处理生成hello.i,hello.i经过编译生成hello.s,hello.s经过汇编生成hello.o也就是可重定向目标程序,hello.o再经过链接就可以生成hello.out可执行程序,当运行hello.out时,系统会先fork一个新的进程,并在新的进程中使用execve加载hello.out,在这个过程中进程管理和计算机内部的地址管理都发挥了至关重要的作用,另外系统的I/O也发挥了它们的作用,最终hello.out执行完后被父进程回收,结束自己的历程。

通过本次对“hello”一生的回顾,我对计算机是如何在深层对源程序进行处理的有了更深的了解,对计算机的整个运行逻辑和机制有了清晰的认识,更重要的是,本次论文的编写帮助我将各个章节的知识联系起来,让我对计算机系统有了一个全面的认识。

(结论0分,缺失 -1分,根据内容酌情加分)

附件

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

hello.i:cpp根据以字符#开头的命令,修改原始的C程序。主要是将头文件,例如stdio文件插入程序文本中,得到新的C程序。

hello.s:编译器将C语言翻译成汇编语言,作为中间的过度阶段。

hello.o:汇编器将汇编语言转化为机器可读的机器语言。

hello:源程序中调用了printf,getchar,sleep,atoi等函数。利用连接器,将C语言函数库中相应的可连接文件与3中的文件连接,生成可执行的文件。

hello_o.elf:hello.o的可执行可连接格式。

hello_oo.elf:hello文件的elf格式。

hello.txt:hello文件的反汇编代码文件

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

参考文献

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

[1]  https://blog.csdn.net/sy06106/article/details/118274118

[2]  《深入理解计算机系统》

[3]  https://blog.csdn.net/LWuoa/article/details/124845263?spm=1001.2014.3001.5501

[4]   https://chat.aidutu.cn/#/chat/1683187740535

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



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有