2021-06-27

计算机系统

大作业

题 目 程序人生-Hello’s P2P
专 业 计算机
学   号 1190200205
班   级 1903010
学 生 史雨菲  
指 导 教 师 史先俊

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

关键词:关键词1程序
关键词2 一生
程序的一生要经过预处理,编译,汇编,链接,加载,运行,收回的全过程,今天我们就一起体验一起经历一下它复杂的一生。
(摘要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:
P2P的过程就是从文本文件到可执行文件的过程,hello.c的源程序(即文本)program,经过预处理器(cpp)修改成为hello.i文件,接着通过编译器成为汇编程序,然后通过汇编器转化为可重定位目标文件hello.o,最后通过链接器变为我们所熟知的可执行目标程序hello,通过shell fork和execve产生process。

020:
从无到有到无,在shell调用fork execve产生进程后,程序映射相应的虚拟内存,在经过程序入口和main函数后运行结束,程序终止,父进程shell回收子进程,原来占据的内存也全被释放。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
硬件环境:X64 CPU;2GHz;2G RAM;256GHD Disk 以上
软件环境:Windows7 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位
开发工具:GDB/OBJDUMP;EDB;gedit+gcc;CodeBlocks 64位等。
1.3 中间结果
hello.i 预处理后修改了的源程序
hello.s 汇编生成的hello的汇编程序
hello.o 编译生成的hello的可重定位目标程序
hello 链接生成的hello的可执行目标程序
1.4 本章小结
Hello的一生探索要上路了!
(第1章0.5分)

第2章 预处理
2.1 预处理的概念与作用
将源程序.c文件通过预处理器变成.i文本文件
作用:
1.将源文件中用#include形式声明的文件复制到新的程序中。比如hello.c第6-8行中的#include<stdio.h> 等命令告诉预处理器读取系统头文件stdio.h unistd.h stdlib.h 的内容,并把它直接插入到程序文本中。
2.用实际值替换用#define定义的字符串
3.根据#if后面的条件决定需要编译的代码

2.2在Ubuntu下预处理的命令
gcc -m64 -Og -no-pie -fno-PIC -E hello.c -o hello.i
应截图,展示预处理过程!
在这里插入图片描述

2.3 Hello的预处理结果解析
.c文本文件只有数十行,但是.i文本文件有几千行,说明头文件中蕴含着许许多多的内容
2.4 本章小结
预处理只是程序一生历险的刚刚开始,后面还有很多更复杂的操作等着它。

(第2章0.5分)

第3章 编译
3.1 编译的概念与作用
进行语法分析和词法分析
将预处理后的c语言文件编译成汇编语言文件
注意:这儿的编译是指从 .i 到 .s 即预处理后的文件到生成汇编语言程序
3.2 在Ubuntu下编译的命令
gcc -m64 -Og -no-pie -fno-PIC – S hello.c -o hello.s
在这里插入图片描述

应截图,展示编译过程!
3.3 Hello的编译结果解析

此部分是重点,说明编译器是怎么处理C语言的各个数据类型以及各类操作的。应分3.3.1~ 3.3.x等按照类型和操作进行分析,只要hello.s中出现的属于大作业PPT中P4给出的参考C数据与操作,都应解析。
Hello.s
在这里插入图片描述

3.3.1算术操作

3.3.2控制转移
(1)if-else(关系操作) Cmpx操作数1,操作数2 jxx条件跳转语句实现,往下跳
在这里插入图片描述

(2)for Cmpx操作数1,操作数2 jxx条件跳转语句实现,往上跳
在这里插入图片描述

3.3.3函数操作
(1)调用
在这里插入图片描述

(2)返回
在这里插入图片描述

(3)参数传递
在这里插入图片描述

3.3.4数据
1.常量
在这里插入图片描述

2.局部变量赋初值 int i=0
在这里插入图片描述

3.参数 argv[0]
数组操作argv[1],argv[2]
在这里插入图片描述
在这里插入图片描述

3.4 本章小结

编译是非常重要的一环,现在我们已经有了汇编语言代码了,它和机器语言有着相似的格式,但是她还仍是文本文件,我们还要继续向前走。
(第3章2分)

第4章 汇编
4.1 汇编的概念与作用
汇编器(as)将.s汇编程序翻译成机器语言指令,把这些指令打包成可重定位目标程序的格式,并将结果保存在.o目标文件中,.o文件是一个二进制文件,它包含程序的指令编码。这个过程称为汇编,亦即汇编的作用。
注意:这儿的汇编是指从 .s 到 .o 即编译后的文件到生成机器语言二进制程序的过程。
4.2 在Ubuntu下汇编的命令
应截图,展示汇编过程!
在这里插入图片描述

4.3 可重定位目标elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
Readelf -a hello.o
ELF头信息
在这里插入图片描述

节头显示各个节的位置
在这里插入图片描述

. text : 已编译程序的机器代码
. rodata : 只读数据,比如printf语句中的格式串和开关语句的跳转表
. data : 已初始化的全局和静态C变量
. bss : 未初始化的全局和静态C变量
. symtab :一个符号表,它存放在程序中定义和引用的函数和全局变量的信息
. strtab : 一个字符串表,其内容包括 .symtab中的符号表,以及节头部中的节
在这里插入图片描述

重定位节及符号表
其中.rela.text节是一个.text节中位置的列表。当链接器把这个目标文件和其他文件组合时,需要修改这些位置。
.rela.eh_frame节包含了对en_frame节的重定位信息。
其中,Offset是需要被修改的引用的字节偏移(在代码节或数据节的偏移),Info指示了重定位目标在.symtab中的偏移量和重定位类型,Type表示不同的重定位类型,例如图中R_X86_64_PC32就表示重定位一个使用32位PC相对地址的引用。Sym. Name表示被修改引用应该指向的符号,Append用于一些类型的重定位要使用它对被修改引用的值做偏移调整。

4.4 Hello.o的结果解析
objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
在这里插入图片描述

说明机器语言的构成,与汇编语言的映射关系。特别是机器语言中的操作数与汇编语言不一致,特别是分支转移函数调用等。

机器语言是二进制语言,一条汇编语言有一到多个字节构成
1) 可以看出,汇编语言中操作数是十进制的,而机器语言反汇编得到的操作数是十六进制的。
2) 对全局变量(即字符串常量)的引用,汇编语言中是用的全局变量所在的那一段的名称加上%rip的值,而hello.o中用的是0加%rip的值,因为当前为可重定位目标文件,之后还需经过重定位方可确定其具体位置,所以这里都用0来代替。
3) 对分支转移,hello.s的汇编语言中在跳转指令后用对应段的名称(如.L3)表示跳转到的位置,而hello.o中因为每行指令都被分配了对应的地址(从main函数第一条指令地址为0开始),在跳转指令后用跳转目的的地址来表示跳转到的位置。
4) 函数调用hello.s中的汇编语言在函数调用时,在call指令后用函数的名字表示对其调用,而反汇编指令在call指令后加上下一条指令的地址来表示,观察机器语言,发现其中操作数都为0,即函数的相对地址为0,因为再链接生成可执行文件后才会生成其确定的地址,所以这里的相对地址都用0代替
4.5 本章小结
汇编产生了可重定位目标文件,它是二进制形式的,但是里面的函数和符号的地址现在都是不确定的,需要下一步连接操作的重定位。
(第4章1分)

第5章 链接
5.1 链接的概念与作用
概念:链接是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可以被加载(复制)到内存并执行。它可以执行于编译时,即在源代码被翻译成机器代码时也可以执行于加载时,也就是在程序被加载器加载到内存并执行时;甚至执行于运行时,也就是由应用程序来执行。
作用:把预编译好了的若干目标文件合并成为一个可执行目标文件。使得分离编译称为可能,不用将一个大型的应用程序组织为一个巨大的源文件,而是可以把它分解为可独立修改和编译的模块。当改变这些模块中的一个时,只需简单重新编译它并重新链接即可,不必重新编译其他文件。
5.2 在Ubuntu下链接的命令
(以下格式自行编排,编辑时删除)
使用ld的链接命令,应截图,展示汇编过程! 注意不只连接hello.o文件
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的格式
分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。

在这里插入图片描述
在这里插入图片描述

在之前的.o文件中,所有的地址位都是零,而在可执行文件中,这些节都有了自己的地址。其实从名字上就看出来,可重定位说明这还未定位,而在可执行文件中,这些代码都已经定位到最终要执行的地址,所以涉及定位的节像rel.text等就没有了。
5.4 hello的虚拟地址空间
使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。
通过readelf查看hello的Program Headers,可发现其中列出的虚拟地址在edb的Data Dump中都能找到对应的位置。
还可发现Data Dump是从地址0x400000开始的,并且该处有ELF的标识,可以判断从可执行文件时加载的信息(只读代码段,读/写段)是从地址0x400000处开始的。
在edb中查看Symbols选项,并与5.3中列出的虚拟地址各段信息做对比,可以看到都显示出了匹配的相同地址。

5.5 链接的重定位过程分析
objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。
结合hello.o的重定位项目,分析hello中对其怎么重定位的。
在这里插入图片描述

根据hello.o中的重定位条目,采取pc相对寻址或者绝对寻址进行重定位。
5.6 hello的执行流程
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。
_dl_start 地址:0x7ff806de3ea0
_dl_init 地址:0x7f75c903e630
_start 地址:0x400500
_libc_start_main 地址:0x7fce59403ab0
_cxa_atexit 地址:0x7f38b81b9430
_libc_csu_init 地址:0x4005c0
_setjmp 地址:0x7f38b81b4c10
_sigsetjmp 地址:0x7efd8eb79b70
_sigjmp_save 地址:0x7efd8eb79bd0
main 地址:0x400532
(puts 地址:0x4004b0
exit 地址:0x4004e0) (argc!=3时)
print 地址:0x4004c0
sleep 地址:0x4004f0 (以上两个在循环体中执行10次)
getchar 地址:0x4004d0
_dl_runtime_resolve_xsave 地址:0x7f5852241680
_dl_fixup 地址:0x7f5852239df0
_uflow 地址:0x7f593a9a10d0
exit 地址:0x7f889f672120
5.7本章小结
链接是很重要的一环也是生成可执行文件前的临门一脚。它马上就可以开始执行啦
(第5章1分)

第6章 hello进程管理
6.1 进程的概念与作用
进程是正在执行的程序,进程使一个程序的执行好像独占了CPU和地址空间(通过虚拟地址来实现)
6.2 简述壳Shell-bash的作用与处理流程

  1. Shell等待一个从终端输入的命令
    2.解析命令行参数
    3.判断是否是内置命令
    4.如果是内置命令,立即执行
    5.否则调用fork函数创建一个子进程
    6.再调用execve函数将程序加载到子进程里运行

6.3 Hello的fork进程创建过程
父进程通过调用fork函数创建一个新的运行的子进程。调用fork函数后,新创建的子进程几乎但不完全与父进程相同:子进程得到与父进程虚拟地址空间相同的(但是独立的)一份副本(包括代码、数据段、堆、共享库以及用户栈),子进程获得与父进程任何打开文件描述符相同的副本,这意味着当父进程调用fork时,子进程可以读写父进程中打开的任何文件。fork被调用一次,却返回两次,子进程返回0,父进程返回子进程的PID。子进程有不同于父进程的PID。
6.4 Hello的execve过程
exceve函数在当前进程的上下文中加载并运行一个新程序。exceve函数加载并运行可执行目标文件,并带参数列表和环境变量列表。只有当出现错误时,exceve才会返回到调用程序,否则,exceve调用依一次且从不返回。在exceve加载了可执行目标文件后,他调用启动代码,启动代码设置栈,将可执行目标文件中的代码和数据从磁盘复制到内存中,然后通过跳转到程序的第一条指令或入口点来运行该程序,由此将控制传递给新程序的主函数。
6.5 Hello的进程执行
结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换等等。
系统中通常有许多程序在运行,那么进程会为每个程序提供一个好像它在独占地使用处理器的假象。这时依赖于进程提供的独立的逻辑控制流(由上下文切换机制提供)。如一个系统运行着多个进程,那么处理器的一个物理控制流就被分成了多个逻辑控制流,每个进程1个。这些逻辑流的执行是交错的,它们轮流使用处理器,会存在并发执行的现象。其中,一个进程执行它的控制流的一部分的每一时间段叫做时间片。这样的机制使进程在执行时仿佛独占了处理器。
处理器用某个控制寄存器中的一个模式位来限制一个应用可以执行的指令以及它可以访问的地址空间范围。没有设置模式位时,进程运行在用户模式中,它必须通过系统调用接口才可间接访问内核代码和数据;而设置模式位时,它运行在内核模式中,可以执行指令集中的任何指令,访问系统内存的任何位置。异常发生时,控制传递到异常处理程序,由用户模式转变到内核模式,返回至应用程序代码时,又从内核模式转变到用户模式。
操作系统内核使用上下文切换来实现多任务。内核为每个进程维持一个上下文,它是内核重启被抢占的进程所需的状态,包括通用目的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内核数据结构的值。
进程执行到某些时刻,内核可决定抢占该进程,并重新开启一个先前被抢占了的进程,这种决策称为调度。内核调度一个新的进程运行后,通过上下文切换机制来转移控制到新的进程:1)保存当前进程上下文;2)恢复某个先前被抢占的进程被保存的上下文3)将控制转移给这个新恢复的进程。当内核代表用户执行系统调用时,可能会发生上下文切换,这时就存在着用户态与核心态的转换。
6.6 hello的异常与信号处理
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
异常:
中断:他由处理器外部的I/O设备的信号引起(如Ctrl-Z,Ctrl-C),可能产生信号SIGSTP,它会将程序挂起,直到有下一个SIGCONT信号;也可能产生信号SIGINT,它会将进程终止。
(1) 运行程序时按Ctrl-Z
程序运行时按Ctrl-Z,这时,产生中断异常,它的父进程会接收到信号SIGSTP并运行信号处理程序,然后便发现程序在这时被挂起了,并打印了相关挂起信息。
在这里插入图片描述

(2) Ctrl-Z后运行ps,打印出了各进程的pid,可以看到之前挂起的进程hello。
在这里插入图片描述

(3) Ctrl-Z后运行jobs,打印出了被挂起进程组的jid,可以看到之前被挂起的hello,以被挂起的标识Stopped。
在这里插入图片描述

(4) Ctrl-Z后运行pstree,可看到它打印出的信息

在这里插入图片描述
在这里插入图片描述

(5) 因为之前运行jobs是得知hello的jid为1,那么运行fg 1可以把之前挂起在后台的hello重新调到前台来执行,打印出剩余部分,然后输入hello回车,程序运行结束,进程被回收。
在这里插入图片描述

(6) 重新开始hello,按Ctrl-Z后通过ps得知hello的进程号为3612,那么便可通过kill -9 3612发送信号SIGKILL给进程3612,它会导致该进程被杀死。然后再运行ps,可发现已被杀死的进程hello。
在这里插入图片描述

(7) 运行hello时按Ctrl-C,会导致一个中断异常,从而内核产生信号SIGINT,父进程受到它后,向子进程发生SIGKILL来强制终止子进程hello并回收它。这时在运行ps,可以发现并没有进程hello,可以说明他已经被终止并回收了。
在这里插入图片描述

(8) 运行时不停乱按(包括回车)
发现他会把乱按的字符打印出来,按回车它会换一行,但是这些都不影响程序的正常执行,因为当程序执行时他不会受到外部输入的影响,它会阻塞这些操作产生的信号,而因为之前将大量字符(包括回车)输入到了屏幕上,所以最后不用自己再输入字符来结束程序,而是直接读取之前的输入。
在这里插入图片描述

6.7本章小结
程序运行离不开shell和操作系统提供的进程管理,而运行的过程中会遇到许多异常,这章也是hello很丰富的一个经历。
(第6章1分)

第7章 hello的存储管理
7.1 hello的存储器地址空间
(以下格式自行编排,编辑时删除)
结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。
(1)逻辑地址空间:段地址:偏移地址
23:8048000 段寄存器(CS等16位):偏移地址(16/32/64)
实模式下: 逻辑地址CS:EA =物理地址CS*16+EA
保护模式下:以段描述符作为下标,到GDT/LDT表查表获得段地址,
段地址+偏移地址=线性地址。
(2)线性地址空间: 非负整数地址的有序集合:
{0, 1, 2, 3 … }
(3)虚拟地址空间: N = 2n 个虚拟地址的集合 ===线性地址空间
{0, 1, 2, 3, …, N-1}
(4)物理地址空间: M = 2m 个物理地址的集合
{0, 1, 2, 3, …, M-1}
之前列举的hello所有函数地址以及汇编语言开头的地址都是虚拟地址(同时也是逻辑地址,这是因为Linux所有段基址都是

7.2 Intel逻辑地址到线性地址的变换-段式管理
被选中的段描述符先被送至描述符cache,每次从描述符cache中取32位段基址,与32位段内偏移量(有效地址)相加得到线性地址
在这里插入图片描述

7.3 Hello的线性地址到物理地址的变换-页式管理
线性地址(虚拟地址)由虚拟页号VPN和虚拟页偏移VPO组成。首先,MMU从线性地址中抽取出VPN,并且检查TLB,看他是否因为前面某个内存引用缓存了PTE的一个副本。TLB从VPN中抽取出TLB索引和TLB标记,查找对应组中是否有匹配的条目。若命中,将缓存的PPN返回给MMU。若不命中,MMU需从页表中的PTE中取出PPN,若得到的PTE无效或标记不匹配,就产生缺页,内核需调入所需页面,重新运行加载指令,若有效,则取出PPN。最后将线性地址中的VPO与PPN连接起来就得到了对应的物理地址。
在这里插入图片描述

7.4 TLB与四级页表支持下的VA到PA的变换
虚拟地址VA虚拟页号VPN和虚拟页偏移VPO组成。若TLB命中时,所做操作与7.3中相同;若TLB不命中时,VPN被划分为四个片,每个片被用作到一个页表的偏移量,CR3寄存器包含L1页表的物理地址。VPN1提供到一个L1 PTE的偏移量,这个PTE包含L2页表的基地址。VPN2提供到一个L2 PTE的偏移量,依次类推。最后在L4页表中对应的PTE中取出PPN,与VPO连接,形成物理地址PA。
在这里插入图片描述

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

7.6 hello进程fork时的内存映射
虚拟内存和内存映射解释了fork函数如何为每个新进程提供私有的虚拟地址空间.
为新进程创建虚拟内存
创建当前进程的的mm_struct, vm_area_struct和页表的原样副本.
两个进程中的每个页面都标记为只读
两个进程中的每个区域结构(vm_area_struct)都标记为私有的写时复制(COW)
在新进程中返回时,新进程拥有与调用fork进程相同的虚拟内存
随后的写操作通过写时复制机制创建新页面

7.7 hello进程execve时的内存映射
execve函数在当前进程中加载并运行新程序a.out的步骤:
删除已存在的用户区域
创建新的区域结构
私有的、写时复制
代码和初始化数据映射到.text和.data区(目标文件提供)
.bss和栈堆映射到匿名文件 ,栈堆的初始长度0
共享对象由动态链接映射到本进程共享区域
设置PC,指向代码区域的入口点
Linux根据需要换入代码和数据页面

7.8 缺页故障与缺页中断处理
在这里插入图片描述

  1. 处理器将虚拟地址发送给 MMU
    2-3) MMU 使用内存中的页表生成PTE地址
  2. 有效位为零, 因此 MMU 触发缺页异常
  3. 缺页处理程序确定物理内存中牺牲页 (若页面被修改,则换出到磁盘)
  4. 缺页处理程序调入新的页面,并更新内存中的PTE
  5. 缺页处理程序返回到原来进程,再次执行缺页的指令

7.9动态存储分配管理
(以下格式自行编排,编辑时删除)
分配器将堆视为一组不同大小的 块(blocks)的集合来维护,每个块要么是已分配的,要么是空闲的。
分配器的类型
显式分配器: 要求应用显式地释放任何已分配的快
例如,C语言中的 malloc 和 free
隐式分配器: 应用检测到已分配块不再被程序所使用,就释放这个块
比如Java,ML和Lisp等高级语言中的垃圾收集 (garbage collection)

Printf会调用malloc,请简述动态内存管理的基本方法与策略。
7.10本章小结
虚拟内存是存储管理中很好的抽象,也很难理解透彻,搞清这一章计统的思路才更加清晰了
(第7章 2分)

第8章 hello的IO管理
8.1 Linux的IO设备管理方法
(以下格式自行编排,编辑时删除)
设备的模型化:文件
设备管理:unix io接口
一个 Linux 文件 就是一个 m 字节的序列:
B0 , B1 , … , Bk , … , Bm-1
现实情况: 所有的I/O设备都被模型化为文件:
/dev/sda2(用户磁盘分区)
/dev/tty2(终端)
甚至内核也被映射为文件:
/boot/vmlinuz-3.13.0-55-generic(内核映像)
/proc (内核数据结构)
8.2 简述Unix IO接口及其函数
接口就是连接CPU与外设之间的部件,它完成CPU与外界的信息传送。还包括辅助CPU工作的外围电路,如中断控制器、DMA控制器、定时器、高速CACHE
和关闭文件
open()and close()
读写文件
read() and write()
改变当前的文件位置 (seek)
指示文件要读写位置的偏移量
lseek()

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本章小结
hello的执行离不开程序间的交互和通信。程序通过操作系统提供的服务来语I/O设备等进行通信。正是通过这些功能,才让hello可以通过printf函数展示在终端,让getchar()读取我们输入的字符来结束hello程序人生的最后一段旅程。正是这些,让hello以它所设计的方式展现在了我们的面前,也让它能接受到我们传递的信号。
(第8章1分)
结论
用计算机系统的语言,逐条总结hello所经历的过程。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
1) hello刚开始是以hello.c的形式诞生的,然后通过cpp预处理器产生了hello.i程序。
2) 之后hello.i经过编译器产生了hello.s汇编代码
3) hello.s经过as汇编器产生了hello.o可重定位目标代码
4) 最终经过ld链接器产生了hello可执行代码
5) shell读入命令后调用fork和execve加载运行程序,其中涉及到输入输出IO
6) 在读取hello虚拟地址时通过页表转化为物理地址
7) 通过cache组索引标记位和偏移量对物理地址访问
8) printf函数会调用malloc进行动态内存分配
9) 程序终止,父进程回收子进程
学习c语言的时候只想着写一个程序,但是学完计算机系统并且走进hello的一生后,才对一个程序的执行和它的一生有了更深入的了解和体会。程序的一生真的和人生一样要经历许许多多复杂的事情,现在我感觉自己在面对它们的时候更加有温度了,而不是面对一堆硬邦邦的代码。
( 结论0分,缺失 -1分,根据内容酌情加分)

附件
列出所有的中间产物的文件名,并予以说明起作用。
hello.i 预处理后修改了的源程序
hello.s 汇编生成的hello的汇编程序
hello.o 编译生成的hello的可重定位目标程序
hello 链接生成的hello的可执行目标程序
(附件0分,缺失 -1分)

参考文献
为完成本次大作业你翻阅的书籍与网站等
【1】 https: //blog.csdn.net/qq_41308641/article/details/85459650
【2】https://www.bilibili.com/read/cv4255183/
【3】(美)布赖恩特《深入理解计算机系统 》机械工业出版社,(Bryant,R.E.)2019
【4】史老师课堂ppt

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值