哈尔滨工业大学计算机系统大作业

计算机科学与技术学院

2021年5月

摘  要

本篇论文分析了程序hello的p2p,020过程,根据书籍《深入理解计算机系统》,对从hello程序的编译,到hello程序的运行的整体过程进行了分析与相应概念的介绍。分析内容主要包括hello程序在编译阶段的预处理、编译、汇编、链接过程以及hello在执行过程中涉及到的进程、存储等有关内容,包含了hello程序从零到有,再到零的过程。

关键词:预处理,编译,汇编,链接,进程,信号,异常,存储管理;                            

(摘要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简介

P2P:P2P是指hello由程序hello.c生成可执行文件hello的过程。Hello.c先经过预处理器,预处理器根据#开头的代码修改原始程序,生成hello.i,接下来hello.i经过编译器,通过词法分析、语法分析、语义分析、中间代码生成以及优化等一系列中间操作后,形成汇编程序hello.s的过程,接下来汇编器根据指令集将汇编程序hello.s翻译成机器命令,并按照固定的规则打包,得到可重定位目标文件hello.o,在经过链接后,变为可执行程序hello。在shell中输入./hello后,shell作为父进程会为hello产生一个子进程,hello成为进程。

020:在最初,正在运行的程序只有shell,在通过shell启动hello后,hello成为shell的子进程,hello被映射到虚拟内存上,虚拟内存让每个程序产生自己独占内存的假象。在hello作为进程运行结束后,会由shell进行回收,回收后实现了zero to zero的过程。

1.2 环境与工具

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

Intel(R) Core(TM) i7-10875H cpu

Windows x86

VirtualBox

Ubuntul1860405

Edb

Codeblocks

1.3 中间结果

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

hello.i:hello.c预处理后生成

hello.s:hello.i编译后生成

hello.o:hello.s汇编后生成

hello:hello.o连接后生成

hello.elf:hello.o转化成的elf文件

hello2.elf:hello转化成的elf文件

1.4 本章小结

        本章从整体上大致介绍了hello由程序变为可执行文件,再从执行到被回收的过程,以及给出了本次论文所使用的环境工具的简单介绍。

(第1章0.5分)


第2章 预处理

2.1 预处理的概念与作用

预处理器根据#开头的代码修改原始程序,在编译代码前对源代码进行重新组织与改写,并将头文件的内容插入到程序中。预处理通过预处理指令实现,是整个编译过程的准备操作。

预处理指令主要包括三个部分:

  1. 宏定义:#define等指令,预处理将define后规定的内容换掉原本的字符串,将指定的内容转化为规定的内容。
  2. 文件包括:#include相当于把由include所指定的文件的具体内容导入到程序中,读取外部文件的详细内容与#include进行替换。
  3. 条件编译:根据条件指令选择不同的代码进行编译,通过条件指令规定的内容判断哪些内容该被执行,哪些内容不该被执行。

2.2在Ubuntu下预处理的命令

图 1 预处理命令

图 2 预处理命令结果

2.3 Hello的预处理结果解析

图 3 预处理结果详细

hello.c文件在经过预处理后展开为很多行,hello.c的头部的#include指令全部被替换为源文件内容,而下方的hello.c主函数内的内容则未被修改,除此之外预处理器将开头的注释也全部删去了。

2.4 本章小结

本章详细的介绍了预处理的含义与过程,并实现了hello.c经过预处理转化为hello.i的过程,并对hello.i内部的内容进行了分析,最终与预处理的过程匹配。

(第2章0.5分)


第3章 编译

3.1 编译的概念与作用

hello.i经过编译器,通过词法分析、语法分析、语义分析、中间代码生成以及优化等一系列中间操作后,形成汇编程序hello.s。编译是将原本hello.i中的c语言程序转化为汇编程序的过程,是实现编程语言到机器语言转化的关键步骤之一。        

3.2 在Ubuntu下编译的命令

图 4 编译命令

图 5 编译命令结果

3.3 Hello的编译结果解析

  1. 头部内容解读:

图 6 汇编语言头部

在编译成的汇编语言头部,通过.file标明了文件,.align是用来对齐格式的,而.string在头文件标明了两个字符串,.globl标明了全局函数main,而type表示格式是main

  1. 数据:

图 7 汇编语言中字符串

在汇编语言的头文件中,声明了两个字符串,作为printf的内容

图 8 汇编语言部分内容

在编译过程中,main函数的两个局部变量被存储在栈中-20(%rbp)和-32(%rbp)位置。在main函数中,有将用户栈中内容赋值给rsi和edi寄存器的操作,而栈中-20(%rbp)和-32(%rbp)的内容存储的是main函数的两个参数,rsi和edi也是函数调用参数时优先使用的寄存器,为此两者分别对应局部变量int argc和指针数组char *argc。

而为了区分哪个是指针数组,可以看后续的L4段中内容,其中对-32(%rbp)中的内容不断取出,对其进行加16和加8的操作,是取数组指针指向的地址,并探索数组中第一,第二数的位置的过程,可以判断-32中存储的是指针数组。

int的两个局部变量分别被存储在栈中-20(%rbp)和-32(%rbp)中。

图 9 汇编语言中的函数变量

而在编译的过程中,函数变量i被存储在-4(%rbp)中,在汇编语言中,-4(%rbp)中的值被赋为0,并在后续的操作中每次进行+1,最终与7进行比较,jle跳跃回循环内部分。

  1. 赋值操作

图 10 汇编语言中的赋值

在编译成的汇编语言中有多处赋值操作,但其中大部分对应着从内存中拿取变量到寄存器中,或对寄存器之间的赋值,而被编译成的在原程序中存在的赋值操作为在循环中对循环变量i赋初值0。

  1. 类型转换

图 11 汇编语言中的类型转换

Atoi是一个用于类型转换的函数,其执行过程是把一个字符串变量转化为整数变量,而在hello.c中转化了argv[3]。在编译成的汇编语言中,则是通过函数调用的形式实现的。

  1. 算术操作

图 12 汇编语言中的算术操作

在c语言中,算数操作体现为循环中i变量的自增,在编译成的汇编语言中,自增与addl 1 -4....对应,而汇编语言中的算数操作体现为addq addl和subq,为对栈地址、寄存器数值的算术操作

  1. 关系操作

图 13 汇编语言中的关系操作

在编译成的汇编语言中有两次关系操作,分别对应着源程序中的第一次判断argc!=4,与在循环中的循环结束条件i<8。

  1. 数组指针操作

图 14 汇编语言中的数组指针

数组操作在变量中有提及,为指针数字argv的操作,其中对argc头部所在地址增加8,12,24确定数组内变量所在地址。指针操作体现在每次获取数组内数值时,获取的是指针所指向地址的内存引用。即指针所指向地址所存储的数值。

  1. 控制转移

图 15 汇编语言中的转移

在程序中只有2次控制转移,其中第一次判断argc的数值是否与4完全相等,并进入相等不相等两个分支,第二次在循环中判断i是否小于8,作为循环的终止条件。

  1. 函数操作

图 16 汇编语言中的函数

程序中调用过atoi,puts,exit,sleep,printf,getchar和main几个函数,其中main在最初由globl定义,其中atoi是用来格式转换的,puts和printf分别输出rdi所在位置的字符串,getchar是用来读入字符串的函数,而exit是用来结束运行的,sleep是用来让程序进入等待状态的函数。而atoi的传入参数为argc[3],在汇编中为地址+24 的%rbp的内存引用,通过寄存器rdi传递,sleep的参数为atoi(argc[3]),通过rdi寄存器中存储的值传递,而两次printf的参数分别为lc0和lc1中的字符串,通过寄存器rdi传递,第二次printf的参数还增加了变量argc2和argc1,数值为存储在地址为+8rbp的内存引用和+16rbp的内存引用,通过寄存器rdx和rax传递。Exit有一个传递参数,通过寄存器edi传递,main函数需要两个参数,分别为寄存器rdi的中存储的值与寄存器rsi中存储的地址。而main函数具有返回值,即在ret结束后寄存器eax中保存的数值0,getchar函数的返回值为读入的字符串。

3.4 本章小结

本章给出了编译的定义与作用,并分析了hello.i通过编译器变成hello.s后,hello.s代码中的部分与hello.c的对应情况,并在hello.s中找到程序的关键部分。

(第3章2分)


第4章 汇编

4.1 汇编的概念与作用

汇编指汇编器根据指令集将汇编程序hello.s翻译成机器命令,并按照固定的规则打包,得到可重定位目标文件hello.o的过程。汇编器将汇编程序翻译成二进制的机器命令,为后续的链接做好准备。

4.2 在Ubuntu下汇编的命令

图 17 汇编命令

4.3 可重定位目标elf格式

可重定位目标文件一般可以分为三个部分:elf header,不同的section,以及描述这些section的表。Elf是可执行可链接格式,通过readelf可以查看hello.o在elf格式下的具体内容。

图 18 readelf展示

通过readelf指令将hello.o文件转化为hello.elf后,对hello的可重定位目标elf格式文件进行详细的分析。

  1. elf header

图 19 elf header内容

     Elf header的最开始用16个字节序列序列描述了文件、系统的字节顺序等关键信息,其中,前四个字节为魔数,用来确认文件类型,接下来一个表示elf文件类型,第六个表示字节序,第七个表示版本号,在magic之后elf header介绍了机器和elf文件的一些基本信息。其中包括文件类型、运行该程序的体系结构、文件版本、程序入口地址、节头表、程序头表在文件中的偏移量、header的大小,节头表、程序头表的条目大小以及条目数量等待基本信息。根据信息,可以判断section的起始位置等关键信息。

  1. Section

图 20 section headers内容

在section header中,对应着罗列了elf文件中的12个section,而在整个section headers中,展示了section的名称、大小,起始位置,地址,类型等关键信息,根据这些信息可以判断每个section在elf文件中的位置。

  1. .symtab

图 21 符号表内容

符号表是section中的一部分,为了使不同的目标文件之间能进行链接,必须使用符号才能让链接正确的完成。在符号表中,罗列了elf文件中17个符号的详细数据,其中包括符号的名字、类型、索引值等具体信息。从符号表中,我们可以看到函数main,以及被main引用的puts、exit、printf、atoi、sleep、getchar等函数在符号表中的显现,而局部变量并不会在符号表中。

  1. 重定位节

图 22 重定位节内容

重定位节展示了text段需要重定位的条目的信息,包括其偏移量、名称、类型等参数,重定位节为链接进行重定位操作提供信息,当汇编器遇到一个最终位置不缺定的符号引用,就建立一个重定位条目。

4.4 Hello.o的结果解析

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

图 23 hello.o反汇编

  1. 机器语言

机器语言由操作码和操作数两部分构成,操作码规定指令的操作,指令包括操作码、操作数的地址、操作结果的存储地址、下一条指令的地址。而操作数是操作的对象。而操作码与汇编语言中的指令可以建立关系,操作数与寄存器、即时数等都可以找到对应的橡,指令中下一条指令的地址则可以构建出汇编语言的顺序关系,因此可以找出到汇编语言的映射。

  1. 操作数

在反汇编生成的汇编语言中,所有的即时数都被转换为16进制,而操作数对应的地址,寄存器在反汇编生成的汇编语言中都满足对应关系。与上述.s文件对比,此处统一了所有即时数的格式。

  1. 函数调用

与.s文件对比,反汇编形成的全体函数调用中都用call 地址来替换,而原.s文件使用的是函数名。在.s文件中,调用的函数并未在main中直接定义,因此调用函数直接使用call+公共库中函数名称使用,而在机器语言中,函数都有对应的地址,机器语言只有操作数、操作数的地址的概念,为此反汇编结果出现差异。

  1. 分支转移

在.s文件中,为使分支跳跃的部分更加明显,使用.L2等字符串对不同汇编语言部分进行编号,而机器语言只存储指令对应的地址,并不会对指令进行编号操作,为此反汇编形成的代码中,分支转移的mov指令跟随的是下一条指令所在的地址。

4.5 本章小结

本章介绍了汇编环节的意义与概念,并通过对hello文件经过汇编形成的可重定位目标文件hello.o,以及hello.o的反汇编结果进行了分析,介绍了hello.o在ELF格式下的不同部分含义以及机器语言与汇编程序对应的映射。

(第4章1分)


5链接

5.1 链接的概念与作用

链接是指将各种代码和数据收集并组合成一个文件的过程,而生成的文件可以被加载到内存并执行。链接器通过建立不同模块间的连接,把大型应用程序分解为更小,更好管理的模块。链接可以执行于编译时,也可以执行于加载时、运行时,链接使得大型的程序变得更好管理,以及减少了很多整体编译的复杂工程。

5.2 在Ubuntu下链接的命令

图 24 链接命令

5.3 可执行目标文件hello的格式

分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。

通过同上readelf指令展示hello在elf格式下的内容于hello2.elf中

图 25 elf header内容

在elf header中文件可以发现,此时hello的类型与上述hello.o文件对比已经转化为了EXEC文件,即可执行文件,而程序头表的起始位置在64,节头表的起始位置到了5936,节头表中的条目个数也有所增加,程序入口在0x400550处。而根据程序头表和节头表的条目个数和条目单个大小,可以计算出每个部分的大小,例如section headers的大小为64*25 bytes。

图 26 section headers内容

与hello.o对比,此时section的数量已经变为24个,每个section的

起始位置和偏移量都在表中有详细列明。

图 27符号表内容

符号表的数量有所增加,同样增加了如init函数等在hello.o中不存在的内容。

图 28 重定位节

可重定位节的内容也有所改变,且数目较之前有所减少

5.4 hello的虚拟地址空间

图 29 edb加载结果

用edb加载hello,结果如图所示,接下来从刚刚在elf文件中阅读到的程序入口开始读取虚拟地址空间的各段信息。

图 30 edb data展示

在程序入口前,可以查看到ELF头部的部分显示

查询程序入口处数据显示,按ELF文件头部信息此时与一section相互对应,而在edb中以乱码的方式呈现,通过查找section headers中不同section的起始位置,均可发现与section对应的乱码文件

.fini在对应地址中的内容

..rodata在对应地址中的内容展示

5.5 链接的重定位过程分析

图 31 hello反汇编代码

如图为hello的反汇编代码,hello的反汇编代码已经完成了链接阶段,在汇编代码中,与hello.o的反汇编代码对比给出了公共库中对于printf,exit等一系列函数的定义,而hello.o中只是call连接函数所在地址,而这些函数在公共库中的具体内容正是由链接引入的。在hello的反汇编代码中,所有的跳转与程序的起始位置都有明确的数值,而不是指向0。

而在重定位中,链接器为每个符号都分配了运行时的地址。在hello文件中,链接器将hello.o与公共库中文件的相同类型的section进行合并,程序中每条程序和变量都在合并中被赋予了准确的地址。而在合并后,链接器需要修改函数调用过程中的引用,例如hello.o文件中的call+地址,使后续地址指向合并后函数所在地址。这个过程需要依据hello.o中的可重定位条目进行,当汇编器遇到一个最终位置不确定的引用,就会生成一个重定位条目。

图 32 hello.o反汇编代码

以hello.o中的1c处对于puts的重定位条目举例,链接器通过重定位条目puts的偏移量与main的起始地址的和确定运行时puts所在地址main+0x25,再通过函数puts的起始地址减去运行时地址,再补上addend常量,得到在hello中的地址4004f0。

5.6 hello的执行流程

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

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

图 33 start函数

start 0000000000400550

图 34 libc start main函数

__libc_start_main  0x600ff0

__libc_csu_init 0x400610

图 35 main函数

Main 0x400582

Puts 0x4004f0

0x601018

Exit 0x400530

0x601038

Printf 0x400500

0x601020

Atoi 0x400520

0x601030

Sleep 0x400540

0x601040

Getchar 0x400510

5.7 Hello的动态链接分析

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

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

动态链接器通过section .got实现动态链接的过程,.got在动态链接与共享库之间建立重要项目,hello程序的动态链接项目需要先确定.got表相关位置,为此去之前elf文件中section headers有详细展示。

图 36 section 

前:

后:

Init运行后,.got处存储的信息发生改变,在动态链接过程中,动态链接器根据.got和.plt中内容对.got做出改变,使得.plt指向正确的地址,之后进行动态链接。

5.8 本章小结

本章通过链接的概念与作用,对hello文件的链接过程进行了整体的分析,包括链接对hello的elf格式文件的改变,对比的展示链接在汇编语言中的表现等待内容,并分析了hello的动态链接过程

(第5章1分)


6hello进程管理

6.1 进程的概念与作用

进程是一个正在运行的程序实例,系统中每一个程序都运行在某个进程的上下文中。上下文是由程序正确运行所需要的状态组成的。在系统上运行一个程序时,进程给程序产生了一个假象,让程序觉得自己独占地使用处理器和内存。

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

Shell是指为使用者提供操作界面的命令解析器,它接受使用者的命令,并对命令进行规定的相应的分析,对一连串命令进行解释,并执行命令的内容。

Shell把命令送到内核,并对命令进行解释分析。

每次用户通过shell输入一个可执行目标文件的名字后,shell会创建一个新的进程,并在新的进程的上下文中运行该文件。

6.3 Hello的fork进程创建过程

调用fork函数时,原有的进程会作为父进程生成一个子进程,而每次调用fork有两个返回结果,对于子进程,fork的返回结果为0,对于父进程,fork的返回结果为子进程的pid,为此fork函数可以根据进程建立一个拓扑图表。

当我们在shell中运行hello时,即通过shell输入.hello时,shell确定了我们的命令为一个可执行文件,为此,shell需要为我们的程序建立一个进程,使得程序能在该进程中执行。而shell通过fork建立一个子进程,我们的程序运行在这个子进程中,此时我们的程序是shell程序的子进程。

6.4 Hello的execve过程

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

Execve本身并不会新建一个子进程,而是让当前正在运行的子进程的中间加载一个新程序的上下文,利用当前子进程运行程序。而当execve调用hello时,会先加载hello中的各类信息,并开始运行hello的程序。Exceve会调用加载器执行hello程序,加载器清除和现有子进程有关的内存内容,并为hello创建新的虚拟内存。

6.5 Hello的进程执行

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

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

  1. 逻辑控制流

进程为每个程序提供假象,程序在独占地使用处理器,而实际上,处理器在不同时间段内执行不同的进程,进程是轮流使用处理器的,而进程使用处理器的程序计数器的序列是逻辑控制流。

  1. 进程时间片

进程使用处理器的时间称为进程时间片

  1. 上下文

上下文由程序正确运行所需要的状态组成,状态包括内存中的代码、数据、栈、寄存器内容等等。

  1. 用户态与核心态

处理器提供的机制,其限制一个应用可执行的指令与可访问的空间。而控制寄存器中的模式位决定了当前进程的权限,权限包括内核模式和用户模式。进程最初是运行在用户态中的,而通过中断、故障等信号才能进入内核模式。

  1. Hello的进程

最初,系统中运行的进程只有shell,而在shell判断hello为一个可执行文件时,shell会为hello调用execve函数,把shell的进程状态修改为hello的,并将控制权移交给hello。而在hello刚进入运行时,相当于进程的初始状态,此时hello处在用户模式。在hello进程正常执行的过程中,如果进入分支则会调用sleep函数。sleep函数为hello发送了一个中断信号,使得hello可以在进程中被挂起,hello程序进入内核模式。而sleep函数执行完毕后,hello程序又会被信号调回用户状态,进程重新移交给hello管理,并加载hello程序。

6.6 hello的异常与信号处理

  1. 中断

中断异常是来自处理器外部的IO设备的信号的结果,是异步处理的

图 37 中断异常处理

  1. 陷阱

陷阱是有意的异常,处理程序将控制返回到下一条指令,为用户程序和内核程序之间提供一个接口,叫做系统调用。

图 38 陷阱异常处理

  1. 故障

故障异常是由错误引起的,处理器将控制权转移给故障处理程序,并让故障处理程序进行修正,或通过内核将故障程序终止。

图 39 故障异常处理

  1. 终止

终止是不可恢复的错误的结果,终止会直接通过内核终止应用程序的进行。

  1. 运行结果

图 40 乱按

乱按后程序仍旧正常运行,并最终正确停止

图 41 回车

   在运行过程中不断按回车,程序结束后在shell中视为输入了同等数量的回车,可以判断在运行回程中输入的回车被存入缓存段。

图 42 ctrl c 直接停止

图 43 ctrl z

图 44 ps 出现hello

图 45 jobs hello已为stopped

图 46 pstree

图 47 fg hello恢复运行

图 48 kill

可以看到,对于不同的信息,发送给了hello不同的信号,并且hello根据接受的信号进行了相应的处理。

6.7本章小结

本章简述了进程的概念与shell的作用,并通过shell分析了hello的进程执行过程,利用shell里的一些命令向hello发送不同信号查看结果。是对异常、进程与信号的统一分析。

(第6章1分)


7hello的存储管理

7.1 hello的存储器地址空间

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

结合hello说明逻辑地址、线性地址、虚拟地址、物理地址的概念。

逻辑地址:逻辑地址是程序产生的段与偏移相关地址的一部分,是程序认为的内存、存储等单元的地址逻辑地址指定的是指令或操作数。在ELF文件中的偏移量,偏移地址等数值都标明了逻辑地址。

线性地址:线性地址时逻辑地址和物理地址转换间的中间层。线性地址通过逻辑地址的偏移地址,添加相应段的基地址生成。在分页机制下,线性地址可以线性的转化为物理地址。

虚拟地址:虚拟内存是硬件异常、硬件地址翻译、主存、磁盘文件和内核软件的完美交互。而虚拟地址是虚拟内存中的地址,cpu通过生成一个虚拟地址来访问主存,虚拟地址在被送到内存前先转化到映射的物理地址,通过cpu与操作系统的工作,进行虚拟地址的寻址。而hello运行过程中,反汇编中各个命令等信息存储的地址即为hello使用的虚拟地址。

物理地址:计算机系统的主存被分成由M个连续的字节大小的单元组成的数组,而在数组中每个字节都有一个唯一的物理地址。Cpu访问内存时,可以通过物理地址找到内存中某位置的内容。而在hello已生成后,hello此时使用的地址是虚拟地址,去内存中按照虚拟地址映射到物理地址的方法寻址,才能找到hello的物理地址,hello的物理地址是hello中内容真实在物理内存中存储的位置。

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

Linux通过分段机制,将逻辑地址转化为线性地址。逻辑地址通常由段选择符和段内偏移量组成。段选择符可以帮助系统找到所需段的线性地址,而段内偏移量是指令地址相对于段基址的偏移量。可以在段选择符中的描述符表中找到段基址。Intel把段描述符集中放在GDT或LDT中,段寄存器存放的是段描述符在其中的索引值。而在进行逻辑地址与线性地址的转换时,我们先使用段选择符或段寄存器在GDT或LDT中索引段描述符,在用段描述符中存储的段基址与偏移量做加法,最终得到其对应的线性地址。

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

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

分页机制把线性地址空间和物理地址空间分割成大小等同的块,通过在线性地址空间的页与物理地址空间的页之间建立的映射实现线性地址到物理地址的转换,该映射由映射表来描述。

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

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

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

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

7.6 hello进程fork时的内存映射

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

7.7 hello进程execve时的内存映射

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

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

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

7.9动态存储分配管理

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

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

7.10本章小结

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

(第7章 2分)


8hello的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程序从hello.c中存储的简简单单的文本,被一步步翻译成汇编语言、机器语言,最终与各个库连接形成了可执行的程序文件。这部分时精密的,凝聚了无数前人的心血。运行后的hello进入了进程,经历了在进程中的一系列过程,最终被系统回收。Hello程序的编译到运行看似简单,但实则中间的每个步骤都蕴含了无数的严密的知识体系与框架,这部分在我们平时的编码过程中并未展示给我们,但是是hello能正常工作的必不可少的关键步骤。

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


附件

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

hello.i:hello.c预处理后生成,用来理解预处理全部过程

hello.s:hello.i编译后生成,与之前的.i对照着判断汇编语言生成过程

hello.o:hello.s汇编后生成,ELF文件,用来分析汇编过程

hello:hello.o链接后生成,用来分析链接全部过程

hello.elf:hello.o转化成的elf文件

hello2.elf:hello转化成的elf文件

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


参考文献

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

[1]https://blog.csdn.net/weixin_41143631/article/details/81221777?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165302132416782425164763%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165302132416782425164763&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-81221777-null-null.142^v10^control,157^v4^control&utm_term=c%E8%AF%AD%E8%A8%80%E7%BC%96%E8%AF%91%E8%BF%87%E7%A8%8B&spm=1018.2226.3001.4187

[2]https://blog.csdn.net/qq_14892521/article/details/103460609?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165302141116782425188941%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165302141116782425188941&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-103460609-null-null.142^v10^control,157^v4^control&utm_term=%E9%93%BE%E6%8E%A5&spm=1018.2226.3001.4187

[3]https://blog.csdn.net/cbbc_curry/article/details/113678686?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165302148516780366567199%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165302148516780366567199&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-113678686-null-null.142^v10^control,157^v4^control&utm_term=%E9%87%8D%E5%AE%9A%E4%BD%8D&spm=1018.2226.3001.4187

[4]Randal E.Bryant, David O'Hallaron. 深入理解计算机系统[M]. 机械工业出版社.2018.4 

[5]https://blog.csdn.net/weixin_45506125/article/details/118058719?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165300706716780357213466%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165300706716780357213466&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-3-118058719-null-null.142^v10^control,157^v4^control&utm_term=shell&spm=1018.2226.3001.4187

[6]https://blog.csdn.net/pipcie/article/details/105670156?ops_request_misc=&request_id=&biz_id=102&utm_term=%E9%80%BB%E8%BE%91%E5%9C%B0%E5%9D%80%E5%88%B0%E7%BA%BF%E6%80%A7%E5%9C%B0%E5%9D%80%E6%AE%B5%E5%BC%8F%E7%AE%A1%E7%90%86&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-105670156.142^v10^control,157^v4^control&spm=1018.2226.3001.4187

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值