计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 计算机与电子通信类
学 号
班 级
学 生 于佳兴
指 导 教 师 刘宏伟
计算机科学与技术学院
2024年5月
HelloWorld是几乎每个程序员的第一个项目,我们慢慢输入几行代码,运行后惊喜地看到输出中的“Hello,World!”然而,从代码编辑器中输入代码到运行程序的这个简单过程,实际上反映了计算机科学的核心概念。我们需要理解语法规则、编译原理和操作系统的运行机制。当我们点击运行按钮时,代码被编译成机器可执行的指令,然后由操作系统加载到内存中,并在CPU上执行。在这个过程中,涉及到诸多底层细节,如内存管理、进程调度和指令执行等。
本文通过跟踪hello的一生,介绍了hello从代码编辑器到运行最后结束的过程,对计算机底层进行了较深的分析。
目 录
第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.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简介
P2P:在文本编辑器中将hello的代码输入,并保存为.c格式的文件,形成hello.c文件。这就是程序,这是hello程序的生命周期的开始。在OS(例如Linux)中,通过交互式应用程序Shell,输入命令实现对hello.c从源文件到目标文件的转化。源程序通过cpp(预处理器)预处理,ccl(编译器)编译,as(汇编器)汇编,最后通过ld(链接器)链接生成hello可执行目标程序并将其保存到磁盘中。
020:在Shell运行该hello程序时,Shell调用fork函数创建子进程,并通过execve函数将hello程序载入并创建运行环境,比如分配虚拟内存,运行完成后,Shell回收该进程,释放内存空间。
1.2 环境与工具
硬件环境:X64 CPU Intel Core i7 6700HQ; 3.2GHz; 16G RAM; 1TB HD Disk
软件环境:Microsoft Windows10 Home 64位; VMware Workstation 14 Pro; Ubuntu 18.04
开发工具:gcc,readelf,edb
1.3 中间结果
- hello.c :源代码。hello.i:预处理之后的文本文件。hello.s:编译之后的汇编文件。hello.o:汇编之后的可重定位目标执行。Hello:连接之后的可执行目标文件。disa_hello.s:反汇编hello.o的汇编代码。disa_hello_2.s:反汇编hello的汇编代码
1.4 本章小结
本章主要简单介绍了hello的P2P与020过程,且列出了本次实验环境、中间结果。
(第1章0.5分)
第2章 预处理
2.1 预处理的概念与作用
预处理是计算机在处理一个程序时第一步进行的,即对.c文件进行初步处理将处理后的结果保存在.i文件中,随后计算机再利用其它部分接着对.i文件进行下一步的处理。
作用:
通过#define指令定义宏,并在代码中使用宏来替换特定的值或代码片段。这有助于简化代码,提高代码的可读性和可维护性。
使用#include指令将其他文件的内容包含到当前文件中。这有助于实现代码的模块化和复用,使代码结构更加清晰使用#if、#ifdef、#else等指令实现根据条件选择性地编译不同的代码块。这有助于在不同的执行环境中方便地修改或编译源代码。
2.2在Ubuntu下预处理的命令
命令:cpp hello.c > hello.i
应截图,展示预处理过程!


2.3 Hello的预处理结果解析


除了以上3个文件外,hello.i中还出现了其他文件,说明这3个文件内容中也包括了其他头文件。而经过预处理得到的hello.i内容远多于hello.c。文件开头是预处理器生成的一些相关信息,之后是对头文件stdio.h、unistd.h、stdlib.h中的内容展开,最后是删去所有注释的源代码部分。
2.4 本章小结
本章主要介绍了预处理的概念与作用,以及在Ubuntu下实现了预处理过程,并对预处理得到的hello.i文件进行分析。
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
编译是将高级编程语言(如C、C++、Java等)编写的源代码转换为机器代码(也称为目标代码或可执行代码)的过程。这个过程通常由编译器完成,编译器是一种软件工具,它能够读取源代码,分析其结构,并将其转换为目标代码。机器代码是计算机硬件可以直接执行的二进制指令,这些指令存储在存储器中,并由CPU逐条读取和执行。
作用:
提高程序的执行效率,编译过程中,编译器会对源代码进行优化,生成更高效的机器代码。增强程序的可移植性,编译器可以针对特定的硬件平台生成优化的机器代码,以确保程序能够在目标硬件上高效运行。提供高级抽象和错误检查,高级编程语言提供了更高的抽象层次,使程序员能够使用更易于理解和编写的代码来开发程序。支持模块化编程和代码复用,编译过程还涉及链接阶段,将生成的机器代码与其他库文件链接,生成最终的可执行文件。提高代码的安全性和稳定性,编译过程中的各种检查(如语法检查、类型检查等)可以发现并报告源代码中的潜在问题,从而提高代码的安全性和稳定性。
这儿的编译是指从 .i 到 .s 即预处理后的文件到生成汇编语言程序
3.2 在Ubuntu下编译的命令


应截图,展示编译过程!
3.3 Hello的编译结果解析
3.3.1数据:
常量
汇编语言只取立即数表示常量
Arg!=5

i<10
![]()
Exit(1)
![]()
局部变量
源代码循环中的i,累加与9比较:


源代码中的argc:
与5比较:

3.3.2赋值
为i赋值1:
![]()
I++:
![]()
3.3.3算数操作
I++:
![]()
3.3.4关系操作
比较arg与5:

比较i与10:

3.3.5 数组操作
源代码printf("Hello %s %s\n",argv[1],argv[2])。先在%rax中存储-32(%rbp),再将%rax加上24,最后将%rax指向的数据传递给%rcx;先在%rax中存储-32(%rbp),再将%rax加上8,将%rax指向的数据存储在%rax中,将%rax的值传递给%rsi;也就是argv[1]和argv[2]的值存储在%rsi和%rdx中,最后调用printf函数:

源代码sleep(atoi(argv[4])),将argv[4]存储在%rdi中:

3.3.6控制转移
If指令比较arg!=5,通过cmpl和je进行跳转:

For循环判断i<10

3.3.7函数操作
Main:
传参argc和argv,返回零

printf函数:
源代码printf("用法: Hello 学号 姓名 手机号 秒数!\n")调用时传入字符串的首地址,通过call指令转移到指定程序:

源代码printf("Hello %s %s\n",argv[1],argv[2])调用时传入参数argv[1]和argv[2],通过call指令转移到指定程序:

exit函数:
通过%edi传递参数1,通过call指令转移到指定位置:

sleep函数:
通过%edi传递参数,通过call指令转移到指定位置:

3.4 本章小结
本章主要介绍了编译的概念与作用,在Ubuntu下编译的命令,同时对hello的编译结果进行解析,详细分析了编译器如何处理C语言中的数据、赋值、算术运算、关系操作、数组操作、控制转移和函数操作。
(第3章2分)
第4章 汇编
4.1 汇编的概念与作用
汇编的概念:汇编器(as)将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序的格式,并将结果保存在目标文件hello.o中。(hello.o文件是一个二进制文件)
汇编的作用;将汇编代码转换为二进制文件,也就是机器语言指令,并将指令打包。汇编指令包括数据传输指令、算术和逻辑指令、分支和循环指令、过程调用指令、处理器控制指令,通过这些指令完成汇编的过程。
4.2 在Ubuntu下汇编的命令
4.3 可重定位目标elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
4.3.1 命令

4.3.2 ELF头
ELF头以一个16字节的序列开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。ELF头剩下的部分包含帮助链接器语法分析和解释目标文件的信息。其中包括ELF头的大小、目标文件的类型、机器类型、节头部表的文件偏移,以及节头部表中条目的大小和数量。

4.3.3节头
不同节的位置和大小是由节头部表描述的,其中目标文件中每个节都有一个固定大小的条目。

4.3.4重定位节
重定位节中包含了在代码中使用的一些外部变量等信息,在链接的时候需要根据重定位节的信息对这些变量符号进行修改。链接的时候链接器会根据重定位节的信息对外部变量符号决定选择何种方式计算正确的地址,通过偏移量等信息计算出正确的地址。

4.3.5符号表
.symtab存放在程序中定义和引用的函数和全局变量的信息。

main、puts、exit、printf、atoi、sleep、getchar等函数都在.symtab中出现
4.4 Hello.o的结果解析
(以下格式自行编排,编辑时删除)
objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
说明机器语言的构成,与汇编语言的映射关系。特别是机器语言中的操作数与汇编语言不一致,特别是分支转移函数调用等。
4.4.1objdump命令
命令:objdump -d -r hello.o > hello_obj.txt(将反汇编文件导出至hello_obj.txt)


4.4.2机器语言与汇编语言对比
操作数:
hello.s中的操作数是十进制数,如下图中的$16;而hello.o反汇编中的操作数是十六进制

分支转移:
hello.s中跳转时显示的是段的名字,

函数调用:
hello.s中call指令后显示的是函数名称,如下图的exit;而hello.o的反汇编中call指令后显示的是与main函数的相对偏移地址
![]()

4.5 本章小结
本章主要介绍了汇编的概念与作用,在Ubuntu下汇编的命令,对hello.o的ELF格式进行分析,包括ELF头、节头、重定位节、符号表等内容,对hello.o的结果进行解析,对比分析了hello.o反汇编的结果与hello.s的区别,着重分析了操作数、分支转移、函数调用的区别。有助于理解ELF格式以及汇编语言和机器语言的区别。
(第4章1分)
第5章 链接
5.1 链接的概念与作用
链接的概念:链接是指将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。
链接的作用:使得分离编译成为可能。不用将一个大型的应用程序组织为一个巨大的源文件,而是可以把它分解为更小、更好管理的模块,可以独立地修改和编译这些模块。当改变这些模块中的一个时,只需简单地重新编译它,并重新链接应用,而不必重新编译其他文件。
5.2 在Ubuntu下链接的命令
![]()
5.3 可执行目标文件hello的格式
5.3.1命令

5.3.2ELF头
ELF头以一个16字节的序列开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。ELF头剩下的部分包含帮助链接器语法分析和解释目标文件的信息。其中包括ELF头的大小、目标文件的类型、机器类型、节头部表的文件偏移,以及节头部表中条目的大小和数量。

5.3.3节头
描述了各个节的大小、偏移量和其他属性。链接器链接时,会将各个文件的相同段合并为一个大段,并且根据这个大段的大小以及偏移量重新设置各个符号的地址。

5.3.4重定位节
重定位节内容变为需要动态链接调用的函数,同时重定位类型发生改变。

5.3.5符号表
存放在程序中定义和引用的函数和全局变量的信息,连接后符号表条目增加。

5.4 hello的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。


.init段起始地址:0x401000,text段起始地址:0x4010f0,节头中的各段在edb中均能对应找到,说明节头表中存储各段的起始地址与各段的虚拟地址之间存在对应关系。
5.5 链接的重定位过程分析
5.5.1命令
![]()
5.5.2对比
hello比hello.o增加了一些节,例如.init、.plt、.plt.sec等。

hello比hello中增加了一些函数,例如_init等。

hello删去了hello.o中的重定位条目,hello.o中跳转的目的地址和函数地址都是与main函数的相对偏移地址,而hello中的都是虚拟内存地址。
![]()
![]()
5.6 hello的执行流程
(以下格式自行编排,编辑时删除)
使用gdb/edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程(主要函数)。请列出其调用与跳转的各个子程序名或程序地址。

5.6.1执行过程
从加载hello到_start:程序先调用_init函数,之后是puts、printf等库函数,最后调用_start函数。从_start到call main:程序先调用__libc_csu_init等函数,完成初始化工作,随后调用main函数。从main函数到程序终止:程序执行main函数调用main函数用到的一些函数,main函数执行完毕之后调用__libc_csu_fini、_fini完成资源释放和清理的工作。
5.6.2子程序名或程序地址
0000000000401000 <_init>
0000000000401020 <.plt>
0000000000401090 <puts@plt>
00000000004010a0 <printf@plt>
00000000004010b0 <getchar@plt>
00000000004010c0 <atoi@plt>
00000000004010d0 <exit@plt>
00000000004010e0 <sleep@plt>
00000000004010f0 <_start>
0000000000401120 <_dl_relocate_static_pie>
0000000000401125 <main>
00000000004011c0 <__libc_csu_init>
0000000000401230 <__libc_csu_fini>
0000000000401238 <_fini>
5.7 Hello的动态链接分析
动态链接是Linux系统中一种将程序模块化并在运行时动态组合的机制。在这种机制下,程序被分割成多个模块,这些模块在程序运行时才会被链接起来,形成一个完整的程序实体。
在动态共享链接库中,位置无关代码(PIC)函数的地址在编译时是无法预知的。因此,编译器会为这些函数生成重定位记录,以便动态链接器在程序加载时能够正确地定位这些函数。为了不在程序运行时修改代码段,动态链接器采用了延迟绑定策略,通过过程链接表(PLT)和全局偏移量表(GOT)来实现。
前后变化:


5.8 本章小结
本章系统地整理了程序链接和执行过程,详细分析了 “hello” 程序的 ELF 文件内容和其虚拟地址空间。我们通过符号解析和重定位,将多个可重定位的目标文件组合成一个可执行文件。在程序执行过程中,当调用共享库函数时,由于定义这些函数的共享模块可以在运行时加载到任意位置,因此我们需要进行动态链接。
(第5章1分)
第6章 hello进程管理
6.1 进程的概念与作用
进程的概念:进程的经典定义就是一个执行中程序的实例。
进程的作用:每次用户向shell输入一个可执行目标文件的名字,运行程序时,shell就会创建一个新的进程,然后在这个新进程的上下文中运行这个可执行目标文件。应用程序也能够创建新进程,并且在这个新进程的上下文运行它们自己的代码或其他应用程序。进程提供给应用程序两个关键抽象:一个独立的逻辑流,它提供一个假象,好像我们的程序独占地使用处理器。一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用内存系统。
6.2 简述壳Shell-bash的作用与处理流程
Shell 是一个命令行解释器,它为用户提供了一个向操作系统发送请求以便运行程序的高级接口。bash 是 Bourne Again SHell 的缩写,是一个由 GNU 项目为 GNU 操作系统开发的一个 Shell 程序。bash 读取用户输入的命令,然后执行这些命令。
bash 的处理流程大致如下:启动:当用户打开一个终端时,bash 会被启动。读取输入:bash 会在命令提示符下等待用户输入命令。解析命令:bash 会解析用户输入的命令,确定要执行的命令和参数。执行命令:bash 会执行解析后的命令。如果命令是内建的,bash 会自己执行;如果命令是外部的,bash 会启动一个新的进程来执行。输出结果:bash 会显示命令的执行结果。回到第2步,等待下一个命令。
6.3 Hello的fork进程创建过程
父进程通过调用fork函数创建一个新的运行的子进程;子进程返回0,父进程返回子进程的PID;新创建的子进程几乎但不完全与父进程相同:子进程得到与父进程虚拟地址空间相同的一份副本(代码、数据段、堆、共享库以及用户栈);子进程获得与父进程任何打开文件描述符相同的副本,子进程有不同于父进程的PID;fork函数:被调用一次,却返回两次。
6.4 Hello的execve过程
execve函数在当前进程的上下文中加载并运行一个新程序。execve函数加载并运行可执行目标文件,且带参数列表和环境变量列表。只有当出现错误时,execve才会返回到调用程序。所以,与fork依次调用返回两次不同,execve调用一次并从不返回。在execve加载了可执行目标文件之后,其调用启动代码。启动代码设置栈,并将控制传递给新程序的主函数。
6.5 Hello的进程执行
进程上下文信息:系统中的每个程序都运行在某个进程的上下文中。上下文是由程序正确运行所需的状态组成的。这个状态包括存放在内存中的程序的代码段和数据段,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。
进程时间片:一个进程执行它的控制流的每一部分的每一时间段叫做时间片。
进程调度的过程:在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占了的进程。这种决策就叫做调度,是由内核中被称为调度器的代码处理的。在内核调度了一个新的进程运行后,他就抢占当前进程,并使用一种称为上下文切换的机制来将控制转移到新的进程,上下文切换保存现场(当前进程的上下文信息);恢复现场(某个先前进程被抢占的进程被保存的上下文);将控制传递给这个新恢复的进程。
用户态与核心态转换:运行应用程序代码的进程初始时是在用户模式中的。进程从用户模式变为内核模式的唯一方法是通过诸如中断、故障或者陷入系统调用这样的异常。当异常发生时,控制传递到异常处理程序,处理器将模式从用户模式变为内核模式。处理程序运行在内核模式中,当它返回到应用程序代码时,处理器就把模式从内核模式改回到用户模式。
6.6 hello的异常与信号处理
(以下格式自行编排,编辑时删除)
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
6.6.1异常:
中断(异步异常):处理器外部I/O设备引起;
陷阱(同步异常):有意的,执行指令的结果;
故障(同步异常):不是有意的,但可能被修复;
终止(同步异常):非故意,不可恢复的致命错误造成。
6.6.2信号
中断:信号SIGTSTP,默认行为是停止直到下一个SIGCONT;
终止:信号SIGINT,默认行为是终止。
6.6.3处理异常的方式
中断:

陷阱:

故障:

终止:

6.6.4命令,异常与信号的处理
正常运行时

乱按时:程序依旧运行

Ctrl-Z后运行ps命令:Ctrl-Z挂起前台作业,ps显示进程的详细信息:

Ctrl-Z后运行jobs命令:Ctrl-Z挂起前台作业,jobs显示任务列表和任务状态:

Ctrl-Z后运行pstree命令:Ctrl-Z挂起前台作业,pstree以树状结构显示进程之间的关系:


Ctrl-Z后运行fg命令: fg %n使第n个任务在前台运行:fg%1

Ctrl-Z后运行kill命令:Ctrl-Z挂起前台作业,kill杀死进程:

Ctrl-C:发送SIGINT信号,结束hello

6.7本章小结
本章主要介绍了进程的概念与作用,程序,作为指令、数据及其组织结构的集合体,而进程则是这些程序在操作系统中的实际运行实体。简而言之,进程是程序在执行状态下的具体表现。在hello进程的运行期间,内核扮演着至关重要的管理角色,它负责决定何时对hello进程进行上下文切换,以确保系统资源的有效分配和多个进程间的平滑调度。壳Shell-bash的作用与处理流程、fork进程创建过程、execve过程、进程执行和异常与信号处理等内容
(第6章1分)
第7章 hello的存储管理
7.1 hello的存储器地址空间
逻辑地址:逻辑地址(Logical Address)是指由程序hello产生的与段相关的偏移地址部分(hello.o中)。
线性地址:段地址+偏移地址=线性地址,线性地址是逻辑地址到物理地址变换的中间结果。如hello中代码与数据的地址。
虚拟地址:虚拟内存是对整个内存的抽象描述,是相对于物理内存来讲的。虚拟内存也就是线性地址空间。这些地址经过转换会变成实际地址(物理地址)
物理地址:物理地址(PA)是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。如果启用了分页机制,那么hello的线性地址会使用页目录和页表中的项变换成hello的物理地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理
7.2.1
段寄存器:有在运行时创建的栈,运行时被申请的内存空间堆(malloc),代码段,数据段

段选择符:

TI=0,选择全局描述符表(GDT),TI=1,选择局部描述符表(LDT); RPL字段表示CPU的当前特权级。RPL=00,为第0级,位于最高级的内核态,RPL=11,为第3级,位于最低级的用户态,第0级高于第3级;高13位-8K个索引用来确定当前使用的段描述符在描述符表中的位置。
段描述符:
段描述符是一种数据结构,实际上就是段表项,分两类:用户的代码段和数据段描述符、系统控制段描述符,其中系统控制段描述符又分两种:特殊系统控制段描述符,包括:局部描述符表(LDT)描述符和任务状态段(TSS)描述符;控制转移类描述符,包括:调用门描述符、任务门描述符、中断门描述符和陷阱门描述符。
描述符表:
描述符表实际上就是段表,由段描述符(段表项)组成。有三种类型:全局描述符表GDT:只有一个,用来存放系统内每个任务都可能访问的描述符,例如,内核代码段、内核数据段、用户代码段、用户数据段以及TSS(任务状态段)等都属于GDT中描述的段;局部描述符表LDT:存放某任务(即用户进程)专用的描述符;中断描述符表IDT:包含256个中断门、陷阱门和任务门描述符。
Intel处理器的存储器寻址:

段式管理:
根据段选择符定位到相应的段描述符,根据段描述符在描述符表中得到相应的段基址,加上偏移量,得到线性地址。
7.3 Hello的线性地址到物理地址的变换-页式管理
页表 是一个页表条目 (Page Table Entry, PTE)的数组,将虚拟页地址映射到物理页地址。
页命中:虚拟内存中的一个字存在于物理内存中,即(DRAM缓存命中)。
缺页及缺页处理:引用虚拟内存中的字,不在物理内存中。缺页导致页面出错 (缺页异常);缺页异常处理程序选择一个牺牲页;导致缺页的指令重新启动: 页面命中。
分配一个新的虚拟页:内核在磁盘上分配,并将页表指向这个位置。

7.4 TLB与四级页表支持下的VA到PA的变换
若TLB命中,则MMU从TLB中取出相应的PTE,将这个虚拟地址翻译为物理地址;若TLB不命中,根据VPN1在一级页表选择对应的PTE,该PTE包含二级页表的基地址;根据VPN2在二级页表选择对应的PTE,该PTE包含三级页表的基地址;根据VPN3在三级页表选择对应的PTE,该PTE包含四级页表的基地址;在四级页表取出对应的PPN,与VPO串联起来,就得到相应的物理地址。
7.5 三级Cache支持下的物理内存访问
首先访问一级Cache,寻找该物理内存对应的内容是否已被缓存且有效,若已被缓存且有效,则缓存命中;否则缓存不命中,则需要访问二级Cache;若二级Cache中依然缓存不命中,则需要访问三级Cache,直到访问主存。将访问到的内容分别加载进上一层缓存,再进行后续操作
7.6 hello进程fork时的内存映射
为新进程创建虚拟内存
创建当前进程的链表和页表的原样副本。
两个进程中的每个页面都标记为只读
两个进程中的每个区域结构都标记为私有的写时复制(COW)
在新进程中返回时,新进程拥有与调用fork的父进程相同的虚拟内存
随后的写操作会通过写时复制机制创建新页面
7.7 hello进程execve时的内存映射
execve函数在当前进程中加载并运行包含在可执行目标文件hello中的程序,用hello程序有效地替代了当前程序。加载并运行hello需要以下几个步骤:
删除已存在的用户区域。删除当前进程虚拟地址的用户部分中的已存在的区域结构。
映射私有区域。为新程序的代码、数据、bss和栈区域创建新的区域结构。所有这些新的区域都是私有的、写时复制的。代码和数据区域都被映射为hello文件中的.text和.data区.bss区域是请求二进制零的,映射到匿名文件,其大小包含在hello中。栈和堆区域也是请求二进制零的,初始长度为零。
映射共享区域。如果hello程序与共享对象(或目标)链接,那么这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。
设置程序计数器(PC)。execve做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向代码区域的入口点。
7.8 缺页故障与缺页中断处理
DRAM缓存不命中称为缺页。CPU引用了VPm中的一个字,VPm并未缓存在DRAM中。地址翻译硬件从内存中读取PTEm,从有效位推断出PTEm未被缓存,并且触发一个缺页异常。缺页异常调用内核中的缺页异常处理程序,该程序会选择一个牺牲页(假设其为VPn)。如果VPn已经被修改了,那么内核就会将它复制回磁盘。无论哪种情况,内核都会修改VPn的页表条目,反映出VPn已经不在缓存在主存中这一事实。
接下来,内核从磁盘复制VPm到内存中,更新PTEm,随后返回。当异常处理程序返回时,它会重新启动导致缺页的指令,该指令会把导致缺页的虚拟地址重发送到地址翻译硬件。
7.9动态存储分配管理
动态内存分配器维护着一个进程的虚拟内存区域,称为堆。系统之间细节不同,但是不失通用性,假设堆是一个请求二进制零的区域,它紧接着未初始化的数据区域后开始,并向上生长。对于每个进程,内核维护着一个变量brk,它指向堆的顶部。
分配器将堆视为一组大小不同的块的集合来维护。每个块就是一个连续的虚拟内存片,要么是已分配的,要么是空闲的。已分配的块显式地保留为供应用程序使用。空闲块可用来分配。空闲块保持空闲,直到它显式地被应用所分配。一个已分配的块保持已分配状态,直到它被释放,这种释放要么是应用程序显式执行的,要么是内存分配器自身隐式执行的。分配器有两种基本风格。两种风格都要求应用显式地分配块。它们的不同之处在于由哪个实体来负责释放已分配的块。显式分配器,要求应用显式地释放任何已分配的块。隐式分配器,另一方面,要求分配器检测一个已分配块何时不再被程序所使用,那么就释放这个块。隐式分配器也叫做垃圾收集器,而自动释放未使用的已分配的块的过程就叫做垃圾收集。
7.10本章小结
本章内容涵盖了hello程序的存储器地址空间、Intel的段式内存管理、以及hello程序的页式内存管理机制。在特定环境下,详细阐述了虚拟地址(VA)到物理地址(PA)的转换过程,以及如何进行物理内存的访问。此外,还介绍了hello进程在fork和execve操作时的内存映射变化,包括缺页故障及其中断处理机制,以及动态存储分配管理的相关知识。
(第7章 2分)
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
(以下格式自行编排,编辑时删除)
设备的模型化:文件
设备管理:unix io接口
8.2 简述Unix IO接口及其函数
(以下格式自行编排,编辑时删除)
8.3 printf的实现分析
(以下格式自行编排,编辑时删除)
[转]printf 函数实现的深入剖析 - Pianistx - 博客园
从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
(以下格式自行编排,编辑时删除)
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
8.5本章小结
(以下格式自行编排,编辑时删除)
(第8章1分)
结论
本文围绕hello所经历的过程展开,其中hello所经历的重要结点包括:
①编写源程序(文本)hello.c;
②hello.c经过预处理器(cpp)的预处理得到修改了的源程序(文本)hello.i;
③hello.i经过编译器(ccl)的编译得到汇编程序(文本)hello.s;
④hello.s经过汇编器(as)的汇编得到可重定位目标程序(二进制)hello.o;
⑤hello.o经过链接器(ld)将其与其它目标文件合并得到可执行目标文件hello;
⑥shell调用fork函数创建子进程;
⑦shell调用execve函数加载hello程序,映射到对应的虚拟内存;
⑧hello程序执行过程中通过进程管理实现异常与信号的处理,存储管理实现内存访问,同时相应的IO设备配合hello程序实现输入输出等功能;
⑨程序结束,父进程对其进行回收,内核将其从系统中清除。
(2)你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
计算机系统的设计与实现首先需要深刻理解计算机系统的各种概念,包括运行机制、原理等,了解程序执行过程中的基本流程,包括预处理、编译、汇编、链接等阶段以及相应的细节。在此基础上,通过对进程管理、存储管理、IO管理等加深对整体框架结构的认识。同时,依据计算机系统的相关原理,可以在安全性、高效性等方面对程序做进一步优化;针对各种可能存在的安全风险进行有效防范。因此,熟练掌握计算机系统相关知识无论是对于加深对计算机的理解,还是编写更加优秀的程序都至关重要。
附件
hello.c :源代码。hello.i:预处理之后的文本文件。hello.s:编译之后的汇编文件。hello.o:汇编之后的可重定位目标执行。Hello:连接之后的可执行目标文件。disa_hello.s:反汇编hello.o的汇编代码。disa_hello_2.s:反汇编hello的汇编代码
参考文献
为完成本次大作业你翻阅的书籍与网站等
[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分)
转载自CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/kaikiideishuu/article/details/147870814



