HIT-ICS2020大作业报告

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3YVwrdfY-1590259653507)(media/df8acd5fc2f7742c471b6b94a471b49f.jpg)]

计算机系统

大作业

题 目 程序人生-Hello’s P2P

计算机科学与技术学院

2020年3月

摘 要

本文以hello程序为例,主要围绕hello的P2P过程以及O2O过程。首先介绍了hello从源程序生成hello的预处理、编译、汇编、链接等阶段,接着阐述hello的进程生成过程,遮羞都是hello的P2P过程。另外,本文还阐述了hello的存储管理以及I/O管理,更加清晰得描述了hello程序的存储方式以及不同类型地址之间的转换与映射。同时,在更加清晰地了解操作系统之后明确了hello地O2O过程。虽然hello只是一个简单地程序,但他从源程序到可执行程序再到如何执行需要经过复杂的过程,本文对这些过程有一个较为清晰地解释。

**关键词:**预处理;编译;汇编;链接;进程管理;I/O;

(摘要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的整个过程。

Hello的P2P过程:

首先在linux系统中GCC编译器驱动程序读取源文件hello.c

并把它翻译成一个可执行目标文件。这个过程需要经过四个阶段:(1)预处理阶段,hello.c在预处理器中被修改,并生成hello.i。(2)编译阶段,编译器cc1将文本文件hello.i翻译成文本文件hello.s,该文件包含一个汇编语言程序,这个程序包含对main函数的定义。(3)汇编阶段,汇编器as将hello.i文件翻译成机器语言指令,并将指令打包成二进制可重定位目标程序,保存在hello.o文件。(4)链接阶段,链接器ld将hello.o和printf.o文件连接起来,,生成二进制可执行目标程序hello。当在shell中输入./hello,shell进行系统调用,将控制权传递给os,os保存shell当前的进程和上下文并为hello创建一个新的进程和上下文,即实现Process。

Hello的O2O过程:(1)hello可执行目标程序生成后等待执行,当在用键盘在shell中敲入“./hello”,该shell将命令经过I/O总线与I/O桥接器逐字读入寄存器,然后依次经过处理器总线、I/O桥接器、存储器总线寄放到内存。(2)敲下回车,结束输入,shell执行一系列指令执行hello可执行文件,将hello木匾文件中的数据和代码从磁盘复制到主存,数据包括最终要打印的字符串。(3)当hello中的数据和代码存放到主存,处理器开始执行main函数中的机器语言指令,指令将字符串从主存复制到寄存器,并进一步经过I/O总线复制到显示器。

1.2 环境与工具

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

硬件环境:X64 CPU;3.10GHz处理器;8G RAM;APPLE SSD AP0512 Disk

软件环境:Windows10 64位;Vmware 15.5.0;Ubuntu 19.04 LTS 64位

开发工具:Visual Studio 2019 64位;CodeBlocks 64位;vi vim/gedit+gcc;EDB

1.3 中间结果

hello.c 源程序

hello.i 预处理之后地程序

hello.s 汇编程序

hello.o 可重定位目标程序

hello 可执行目标程序

hello.elf hello.s的elf文件,方便查看与分析

hello2.elf hello.o的elf文件,方便查看与分析

1.4 本章小结

本章阐述了Hello的P2P和O2O过程,对Hello从源程序Hello.c到Hello可执行目标程序的几个阶段以及Hello如何在os中生成进程有了简单阐释。同时在对O2O过程的解释中说明了Hello可执行程序是如何在I/O与os之间交互执行的。

同时本章列出了该实验的硬件及软件环境和开发工具并列出了本次实验的中间结果文件和各个文件的作用。

(第1章0.5分)


第2章 预处理

2.1 预处理的概念与作用

预处理是C语言的一个重要功能,由预处理器(cpp)负责完成,预处理是在正式编译之前进行的。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。

预处理器根据以字符#开头的命令修改源程序。C语言提供多种预处理功能,主要处理#开始的预编译指令,如宏定义(#define)、文件包含(#include)、条件编译(#ifdef)等。预编译的主要作用如下:

  • 将源文件中以”include”格式包含的文件复制到编译的源文件中。

  • 用实际值替换用“#define”定义的字符串。

  • 根据“#if”后面的条件决定需要编译的代码。

比如Hello.c中#include命令告诉预处理器读取系统头文件stdio.h的内容,并把它插入到程序文本中。得到另一个C程序。

合理使用预处理功能可以使编写的程序更加清晰明了、有更好的可移植性,有更好的模块性便于调试。

2.2在Ubuntu下预处理的命令

gcc -E hello.c  -o hello.i

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tkf5Ytmq-1590259653510)(media/0f91cd3048af66464d65e31d4e15cb83.png)]

图2-1 ubuntu下预处理的指令与结果

2.3 Hello的预处理结果解析

图2-2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nOadhp0f-1590259653511)(media/38a9c21fd78fe8a2a1c73aa2414a80e9.png)]

源程序hello.c内容

以上是源程序的内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1iHRuAPs-1590259653514)(media/17f98f9b55ee59ab1557d5229b1c0f49.png)]

图2-3(1)hello.i文件内容

./media/image5.png

图2-3(2) 文件hello.i内容

以上是预处理之后的文件hello.i,可以看到文件变成了3000多行,源程序中的内容出现在文件尾,并且hello.i中不再包含#include
、#include 、#include
等头文件,而是预处理器读取了它们的内容并把他们插入到文本里。比如对于头文件#include
,预处理器去/usr/include/stdio.h打开它,发现里面还有宏定义,将会接着展开,直到最后的hello.i文件。

2.4 本章小结

本章介绍了Ubuntu下对c源程序预处理的命令,并展示了预处理之后hello.i的文件结果。同时解释了预处理过程,对hello.c到hello.i的过程作出了解释。

(第2章0.5分)


第3章 编译

3.1 编译的概念与作用

编译阶段是编译器(cc1)将hello.i编译成汇编程序hello.s的过程。

在这一阶段,编译器首先检查语法错误和规范性,并确定代码的用途,然后翻译成机器语言指令,生成hello.s汇编语言程序,该程序中包含函数main的定义。汇编语言为不同编译器提供了通用的输出语言。

3.2 在Ubuntu下编译的命令

gcc -S hello.i -o hello.s

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cvTkUrX0-1590259653516)(media/b87cbbfd114c5ed65eb9caf17b50ad58.png)]

图3-1 Ubuntu下编译命令及结果

3.3 Hello的编译结果解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ID9z2DgH-1590259653518)(media/c8307f1e5779cbe01efd9217a3e86626.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8kkTuEjg-1590259653519)(media/a34b14def898da2d41af6536fdbba780.png)]

图3-2 汇编程序内容

3.3.1数据

本程序中主要的数据类型是整型、字符串、和数组

3.3.1.1整型

(1)int i

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VV8kuDEu-1590259653520)(media/2dd7365041433233ad91b116b7342a22.png)]

图 3-3

整型局部变量,保存在栈或寄存器中,i是整型局部变量,保存在用户栈,并被赋初值为0,占用4个

(2)int argc

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C6ATUrOR-1590259653521)(media/feccb960c91f2ba62aefc0a74aba1189.png)]

图3-4

argc是main函数的参数,表示输入的参数的个数,它被保存在%edi中,然后经过数据传送指令保存在寄存器%rbp中

3.3.1.2字符串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fz5pF50J-1590259653523)(media/b094e8287d43fa36ec87cfdbd0cb5c5b.png)]

图3-5

如图3-5所示为字符串部分,如果输入参数个数不等于4,就会为LC0,输出默认输出“用法:
Hello 学号 姓名
秒数!”的内容,如果输入参数个数等于4,则会输出LC1,即Hello加输入的参数内容。

3.3.1.3数组

保存输入参数的数组argv的首地址在寄存器%rsi中,如图3-6,然后将其内容赋给寄存器%rax,分别为三个参数的地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zYDeIDBU-1590259653524)(media/b8664c60383b8274a4ab27982d07e5f4.png)]

图3-6

3.3赋值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wCVf0eDs-1590259653525)(media/29762f79d9d6fb8e13e64aa79a1e6f73.png)]

图 3-7

循环开始前,通过movl命令将i赋处置为0,且movl命令表示传送双字。

3.4算术操作

图3-8显示内容为i++

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kt4IeSKr-1590259653526)(media/bf821710b9e8584a27894283b32545c2.png)]

图3-8

3.5关系操作

如图3-9,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tY5uy3Q0-1590259653528)(media/bba0a36904d1342ca0b818ef62e3f946.png)]

图3-9

判断argc变量是否等于4,即是否输入了4个参数如果等于4,则跳转到L2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ZsZlrHg-1590259653529)(media/613f266d847d1595d42844b1e1ca466e.png)]

图3-10

比较i和7的大小判断循环结束条件,如果i《7那么跳转到L4,下一轮循环。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sP9Qqlmp-1590259653531)(media/c5e6a09ef9c589324f1f52941d37c9bd.png)]

3.6指针/数组/结构操作

图3-11

addq $16,%rax以及addq $8,%rax分别得到argv[1]和argv[2]

3.7控制转移

程序中控制转移有两处:

  1. 根据输入参数是否是4个来决定下一步跳转到哪一条指令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XRvPZFwX-1590259653532)(media/348b4ab62c8dfd8ea2e6a6e76f4807a4.png)]

图 3-12

  1. 根据i和7的大小关系判断是否跳出循环。

如果i小于等于7,则跳转到.L4进行循环,否则的话顺序往下进行getchar等操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BbvkH0xJ-1590259653533)(media/613f266d847d1595d42844b1e1ca466e.png)]

图 3-13

3.8函数

3.8.1main函数

3.8.1.1调用

__libc_start_main系统函数调用main函数,main的函数地址被传给%rip,然后调用

3.8.1.2参数传递

main函数有两个参数,分别为int
argc,和数组argv[],他们分别被存储在寄存器%rdi和%rsi中。如图3-14

3.8.1.3函数返回

如图3-15,将0传给累加器%eax然后返回函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-majHZCbU-1590259653534)(media/4c12694b750c71268bf6c11259037b78.png)]

图 3-14

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sZ0l33tn-1590259653535)(media/949acba8cd03752a1f67b1dcfe11b1fd.png)]

图3-15

3.8.2sleep函数

3.8.2.1函数调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I9PysJ9C-1590259653536)(media/d34a850f16c826825d7e8678354cbc85.png)]

图3-16

如图3-16调用sleep函数。

3.8.2.2参数传递

将atoi的返回值%eax通过%rdi传递给sleep函数。

3.8.2.3函数返回

在sleep中返回。

3.8.3printf函数

3.8.3.1函数调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dv2RnkF4-1590259653537)(media/9b9e45d6867baf434184d02fbf72fe4b.png)]

图3-17

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RQjwVysA-1590259653538)(media/53cf09d011c771fc06f7dd504ea98f96.png)]

图3-18

图3-17printf()由call printf@PLT调用,图3-18printf()由call puts@PLT调用。

3.8.3.2参数传递

for循环中call printf时传入了 argv[1]和argc[2]和argv[3]的地址。

3.8.3.3函数返回

在printf函数中返回。

3.4 本章小结

本章主要介绍了编译阶段生成hello.s文件的命令、过程并对该文件的内容从数据类型、赋值、算术操作、控制转移、函数调用等内容按照汇编语言进行了分析。

对hello.s文件的内容和生成过程有了更清晰地认识。

(第3章2分)


第4章 汇编

4.1 汇编的概念与作用

汇编是汇编器(as)把编译阶段生成的汇编程序hello.s翻译成可重定位目标程序hello.o的过程。在这一过程汇编器as将hello.s翻译成机器语言指令,这些指令打包成可重定位目标程序的格式,并将结果保存在目标程序hello.o中,它是一个二进制文件,包含函数main的指令编码。

4.2 在Ubuntu下汇编的命令

gcc -c hello.s -o hello.o

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZ4SR4yL-1590259653540)(media/ce899672ef812c35f79ebc32ca18d938.png)]

图4-1 Ubuntu下汇编的命令

4.3 可重定位目标elf格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XehQ9qyp-1590259653541)(media/4cb20e5739ca3d182f75be81caef51a9.png)]

分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nRzLs8FQ-1590259653542)(media/a7a6320e0796ac83fd564ad49253e368.png)]

图4-2 生成ELF格式的命令

图4-3 典型ELF文件的格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q2ZnKJiZ-1590259653544)(media/c41511b86148ecb9eaca21a6035574da.png)]

如图4-2所示为生成hello.o的ELF格式的命令。图4-3所示的为典型的ELF文件的格式。

4.3.1 ELF头

图4-4 ELF头的信息

上图中4-4为ELF头所展示出的信息,ELF头以一个16位字节顺序开始,描述生成该文件的系统的字的大小和字节顺序。目标文件的类型是elf可重定位目标文件,机器类型是64位,数据为2进制补码形式小端存储,同时还表示了程序入口点为0x0,以及节头部表中条目大小为64字节,条目数量为14等信息。

4.3.2 节头部表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-53UBszK4-1590259653545)(media/660d994a1d3c158cfa9eb873fc1b7e09.png)]

图 4-4 ELF文件中节的信息

图4-4表示了ELF文件中在ELF头和节头部表之间的各个节的信息,包括节的大小、类型、大小和偏移量。可以看出该ELF文件有:

.text节,该节存放已编译程序的机器代码。

.rela.text节,这是.text节中位置的列表,当链接器把这个文件和其他文件组合时需要修改这些位置。

由于本程序没有未初始化的全局变量和静态C变量,所以没有.data节。

.symtab节是一个符号表,存放在函数中定义和引用的函数和全局变量的信息,不包含局部变量的条目。

.strtab是一个字符串表,其内容包括.symtab和.debug中的符号表。以及节头部中的节名字。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h4tdHXcw-1590259653546)(media/163b8b7fe20847a58cab89089d560b18.png)]

4.3.3 重定位节

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S4YCktf9-1590259653547)(media/654a62e534bf370a7864317b1bb38f9c.png)]

图4-5 ELF中的重定位节

上图中为ELF文件中的可重定位节,可以看出该ELF文件中有.rela.text和

.rela.eh_frame两个重定位节,偏移量是要修改的位置在.text和.eh_frame中的偏移量。有两种类型,分别为R_X86_64_PC32和R_X86_64_PLT32,其中R_X86_64_PC32类型表示重定位一个使用32位PC相对寻址的引用,R_X86_64_PLT32表示过程链接表延迟绑定。

4.3.4 .symtab符号表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4TBcwC80-1590259653549)(media/978196232a345000b238013374a33fb9.jpg)]

图4-6 .symtab符号表

如图4-6所示位.symtab符号表,存放在程序中引用的函数和全局变量的信息。每个重定位文件都有一个符号表,但不包含局部变量条目,可以看出本程序用了一个main函数,puts、exit、printf、atoi、sleep、getchar等函数。

4.4 Hello.o的结果解析

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

objdump -d -r hello.o 分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FQWwAEiO-1590259653550)(media/1c5abd3fd8560cdcbcdfd05885629e90.png)]

图4-7(1)hello.o地反汇编

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NYWUpgel-1590259653551)(media/b15bf8d36a5187ea8dfd6e8a0b734319.png)]

图4-7(2)hello.o的反汇编

不同之处

(1)操作数:hello.s中操作数为10进制,而hello.o中操作数为16进制

./media/image34.png

4-8 hello.s中操作数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lQ87MALQ-1590259653553)(media/e8ae35dcc864e3c7e5691027254fafd3.png)]

4-9 hello.o中操作数

  1. 分支转移

分支转移中hello.s文件跳转指令je后面是跟L2等名称,而hello.o后面是跳转的下一条指令的地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VFyCWtSA-1590259653554)(media/beba22b06465669b13c0e753aad7af3d.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1qYqzaKd-1590259653556)(media/8222723dc63347cb036376e0d0bffda1.png)]

4-10 hello.s中分支转移

4-11 hello.o中分支转移

  1. 函数调用

hello.s文件中函数调用call后面跟函数名称,而hello.o中跟函数起始地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOc3Gq2r-1590259653557)(media/8284bd376f724dd0cae2bad7cd81b5c2.png)]

4-12 hello.s中函数调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E5d4kq5p-1590259653558)(media/5e828154c69614b308357c44fbc2ebf0.png)]

4-13 hello.o中函数调用

4.5 本章小结

本章介绍了汇编阶段的命令及生成文件的过程。还介绍了可重定位文件ELF文件的格式及内容,分析了可重定位目标程序hello.o的ELF文件的相关内容,并且比较了汇编程序hello.s和可重定位目标程序hello.o的不同之处

(第4章1分)


第5章 链接

5.1 链接的概念与作用

概念:链接是将各种代码和片段收集并组合成单一片段的过程,合并后的文件被加载到存储器中运行。

作用:使得分离编译成为可能,不用将一个大型应用程序组织成一个巨大的源文件,而是可以分解成更小、更好管理的模块,可以独立修改和编译这些模块。当改变模块中的一个时只需要重新简单编译他并连接应用,而不需要重新编译其他文件。

5.2 在Ubuntu下链接的命令

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xNKSg5bp-1590259653561)(media/7867fb18437d8f927e3d9c072869cff1.png)]

图 5-1 链接命令

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

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

5.3.1 ELF头

图5-2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eSIZ99q-1590259653562)(media/80f14c6e392088f5a498889f1076119b.png)]

可执行文件hello的ELF头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N5kgsXWO-1590259653563)(media/7b47432fe70a858cc2b07eba354db96f.png)]

程序入口地址在0x4010f0

5.3.2 节头

图 5-3 节头部表

上图5-3显示了hello可执行文件中各个节的信息,如可以看出.text节的起始位置为0x4010f0,还有.data节、符号表等各个节的类型、位置、大小信息。

5.3.3 程序头

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rHFvMdBR-1590259653566)(media/144ac69ff0f591fc0df121831fb702c9.png)]

./media/image44.png

图 5-4 程序头的内容

5.3.4 重定位节

图5-5 重定位节的内容和信息

可执行程序hello有两个重定位节,分别是.rela.dyn和.rela.plt,图5-4显示了这两个节的偏移量、类型、符号值、符号名称等信息。

5.3.4符号表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GlH9FXX9-1590259653567)(media/2f90fb338cae94006f05d4a3fc47e502.png)]

图 5-6(1)hello符号表的信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MBRSvXy-1590259653568)(media/ec3661edc507dd2785605d1b5df9db90.png)]

图5-6(2)hello符号表的信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aytzxl3J-1590259653569)(media/70e87f4afa7a7c8270fb141259b2e89b.png)]

图 5-6(3)hello符号表的信息

hello可执行文件的ELF文件中有两个符号表,分别为.dynsym和.symtab。其中.symtab存放在函数中引用的函数和全局变量的信息。

5.4 hello的虚拟地址空间

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UE1wIqbw-1590259653570)(media/a51e6fded6cc2fd1dd60fcc96e58ff94.png)]

图5-7 edb下查看hello的虚拟空间地址

图5-7显示ELF的起始地址为0x400000,5-8中各个段的地址也均可以在5-7中找到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JIXyOZ4n-1590259653571)(media/068509ba4b6752959835633cb4beb51f.png)]

图5-8 程序头显示的各段信息

5.5 链接的重定位过程分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZGFnaHD4-1590259653571)(media/425f6cbb9abfebf9254be2d593fa06d2.png)]

图 5-9(1)objdump查看hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8v6HRuL-1590259653572)(media/6fc4f8ffa01d8bb5f1da03e9787f9120.png)]

图 5-9(2) objdump查看hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BqzOQ3uy-1590259653573)(media/8988a4ee2b0bbaa80c8f6d464babd59b.png)]

图5-9(3)objdump查看hello

图5-9(4)objdump查看hello

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qu6iEJyi-1590259653575)(media/ebe8e0440e604865e9a21f3f6f598dcb.png)]

5.5.1 hello和hello.o的不同

(1)增加节:hello中增加了.init和.plt节

(2)增加函数:hello中增加了exit、printf、sleep、getchar等函数。

(3)地址不同:hello中访问的是虚拟地址。hello.o的反汇编结果中,各部分的开始地址均为0。

5.5.2 hello的重定位

链接器将所有相同类型的节合并为同一类型的新的节。包括hello.o在内的所有可重定位目标文件中的.data节被全部合并成一个节,这个节成为可以映射到hello中的.data节。然后,连接器将运行时内存地址赋给新节、输入模块定义的每个节和这些模块定义的每个符号。然后全局变量就有了唯一地址。

重定位节中的符号引用。链接器依赖于hello.o中的重定位条目,修改代码节和数据节中对每个符号的引用,使得它们指向正确运行时的地址。

5.6 hello的执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eH0oEjUS-1590259653577)(media/8d61dd2df5bb60475af6551573a77ae9.png)]

图5-10

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VRLaeZNl-1590259653579)(media/c2635bb75408494597e44459910ae0e2.png)]

图5-11

  1. 调用start函数 地址为0x4010f0,如图5-10.

  2. 调用libc_start_main函数,如图5-11

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f79qoLOA-1590259653581)(media/a80f8ca1f684a84c27c943fd848f37c5.png)]

图5-12

(3)传入参数

(4)调用printf函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2YW9A1f-1590259653583)(media/4452695eaa01133d4070baec06558ddd.png)]

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

调用libc-2.27.so!__cxa_atexit

调用libc-2.27.so!__new_exitfn
调用__libc_csu_init

调用__libc_csu_init
调用_init函数

调用libc-2.27.so!_setjmp函数

调用-libc-2.27.so!_sigsetjmp函数
调用–libc-2.27.so!__sigjmp_save函数
调用main
调用puts

调用exit
调用ld-2.27.so!_dl_runtime_resolve_xsave
调用ld-2.27.so!_dl_fixup

调用–ld-2.27.so!_dl_lookup_symbol_x
调用libc-2.27.so!exit

5.7 Hello的动态链接分析

动态链接是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,虽然动态链接把链接过程推迟到了程序运行时,但是在形成可执行文件时,还是需要用到动态链接库。在形成可执行程序时,发现引用了一个外部的函数,此时会检查动态链接库,发现这个函数名是一个动态链接符号,此时可执行程序就不对这个符号进行重定位,而把这个过程留到装载时再进行。

5.8 本章小结

本章介绍了链接的概念、作用以及在ubuntu终端链接的命令。同时分析了hello的ELF文件的相关信息。分析了hello的虚拟地址空间以及重定位过程在edb中执行了hello程序,并观察了执行过程,比如执行过程中的函数调用。最后分析了hello的动态链接。

(第5章1分)


第6章 hello进程管理

6.1 进程的概念与作用

概念:狭义上,进程的经典概念是一个执行中程序的实例。系统中每个程序都在运行某个进程的上下文,上下文由程序正确运行所需的状态组成。广义上,进程是程序在某一数据集合上的一次执行的过程。在传统的操作系统中,进程系统进行资源分配和调度的分配单元和执行单元。

作用:

  1. 进程提供给应用程序两个关键抽象

a.逻辑控制流。每个程序好像在独占使用处理器。通过OS内核的上下文切换机制提供。了解进程可以更好地理解逻辑控制流和进程控制。可以根据功能在资源紧张的情况下杀死某些进程,节约计算机的资源。

b.私有地址空间。每个程序似乎在独占使用内存系统。由OS内核的虚拟内存机制提供。

(2)了解进程可以更好地理解逻辑控制流和进程控制。可以根据功能在资源紧张的情况下杀死某些进程,节约计算机的资源。

了解进程可以帮助了解系统的健康状况,通过查看系统中各个进程的信息如CPU占用率等,同时可以判断异常进程,杀死病毒,从而维护系统正常运行。

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

作用: Shell是一个交互型应用程序,提供用户与操作系统给内核的交互界面。

处理流程:(1)读入用户从shell输入的命令。

  1. 切分读入的字符串来获得所有参数。

  2. 如果时系统内置命令则立刻执行。

  3. 如果不是内置命令则调用执行程序为命令分配子进程来执行。

  4. Shell应该接受键盘输入信号并进行处理。

6.3 Hello的fork进程创建过程

父进程通过调用fork函数来创建一个新的运行的子进程。新的子进程几乎但不完全与父进程相同。子进程得到与父进程用户级虚拟地址空间相同的(但是独立)的一份副本,包括代码和数据段、堆、共享库以及用户栈。子进程还获得与父进程任何打开文件描述符相同的副本,这意味着当父进程调用fork时,子进程可以读写父进程中打开的任何文件。父进程和新创建的子进程之间的最大区别时他们由不同的PID。

fork
函数只被调用一次但是返回两次:一次是在调用进程(父进程)中,一次是在新创建的子进程中。在父进程中,fork返回子进程的PID。在子进程中,fork返回0。

6.4 Hello的execve过程

execve
函数加载并运行可执行目标文件hello,且带参数列表argv和环境变量列表envp。当出现错误时,execve才会返回到调用程序。所以execve调用一次从不返回。

Execve时加载器函数在当前进程中载入并运行程序,加载器删除子进程现有的虚拟内存段,创建一组新的段(栈与堆初始化为0),并将虚拟地址空间中的页映射到可执行文件的页大小的片,新的代码与数据段被初始化为可执行文件的内容,然后跳到start……除了一些头部信息实际没读文件,直到缺页中断。

Execve函数在当前进程的上下文中加载并运行一个新的程序。它会覆盖当前进程的地址空间,但并没有创建一个新进程,新的进程仍然有相同的PID,并且继承了调用execve函数时已打开的所有文件描述符。

6.5 Hello的进程执行

(1)上下文信息:内核为每个进程维持一个上下文。上下文就是内核重新启动一个被抢占的进程所需的状态。它由一些对象的值组成,这些对象包括通用的目的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内核数据结构,比如描述地址空间的页表、包含有关当前进程信息的进程表,以及包含进程已打开文件的信息的文件表。

(2)时间片:一个进程执行它的控制流的一部分的每一时间段叫做时间片。

(3)用户态与核心态:为了使操作系统内核提供一个无懈可击的进程抽象,处理器必须提供一种机制,限制一个应用可以执行的指令以及它可以访问的地址空间的范围。

处理器通常是用某个控制寄存器中的一个模式位来实现这种功能,该寄存器描述了进程当前享有的特权。当设置了模式位时,进程就运行在内核模式(有时叫做超级用户模式)。一个运行在内核模式的进程可以执行指令集中的任何指令,并且可以访问系统中的任何内存位置。

没有设置模式位时,进程就运行在用户模式中,用户模式中的进程不允许执行特权指令,比如停止处理器,改变模式位,或者发起一个I/O操作。也不允许用户模式中的进程直接引用地址空间内核区的代码和数据。任何这样的尝试都会导致致命的保护故障。反之,用户程序必须通过系统调用接口间接地访问内核代码和数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qP9hqjxb-1590259653584)(media/a18899411df8fa9934d20bac934c0fa2.png)]

(4)进程调度:在进程执行地某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占了地进程,这种决策叫调度,是由内核中称为调度器地代码处理的。当内核选择一个新的进程运行时,他就抢占当前进程,并使用一种称为上下文切换的机制来控制转移到新的进程,上下文切换a)保存当前进程地上下文,b)恢复某个先前被抢占地进程被保存的上下文,c)将控制传递给这个新恢复的进程。

图6-1 上下文切换剖析

假设图6-1所示为hello的上下文切换与进程调度过程,进程A初始在用户模式运行,如果没有异常或中断,该进程将正常运行,如果有异常,则在内核模式进行上下文切换。当程序运行到sleep函数时,进入内核模式,内核处理休眠请求并将控制权转给另一个进程,计时器开始计时,当计时器到达时间后,会产生中断信号,中断正在进行的进程,并进行上下文切换,回到hello在sleep之前的进程,控制权回到hello。当循环结束,hello调用getchar函数,进入内核模式并进行上下文切换,控制权又转移给其他进程,当键盘输入完成,产生键盘终端信号,又再次进行上下文切换,回到hello进程。

6.6 hello的异常与信号处理

6.6.1异常、信号及其处理方式

(1)中断

中断时来自处理器外部的I/O设备的信号的结果。I/O设备会向处理器芯片上的一个引脚发送信号,并将异常号放到系统总线上,来触发中断,异常号标识引起中断的设备。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gVVw2cZb-1590259653585)(media/d3679744f562b6f5cc228e51da22f4ea.png)]

图6-2 中断处理过程

图6-2所示为中断处理过程。在当前指令执行后,处理器注意到中断引脚电压变高,就从系统总线读取异常号,然后调用适当的中断处理程序。当处理程序返回时,将控制返回给下一条指令(即如果没有发生中断,在控制流中会在当前指令之后的那条指令)。结果时程序继续执行,就好像没有发生中断一样。

(2)陷阱

陷阱是有意异常,是执行一条指令的结果。陷阱在用户程序和内核之前提供一个像过程一样的接口,叫做系统调用。陷阱处理程序将控制返回到下一条指令。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QkYqOhoJ-1590259653587)(media/2ddafe074efd4114b38087d160497cc7.png)]

图6-3 陷阱处理过程

用户程序经常向内核请求服务,为了允许对内核服务的受控的访问,处理器提供一系列特殊“syscall
n”指令,当用户程序想请求服务n,可以执行这条指令,就会导致一个到异常处理程序的陷阱,这个处理程序解析参数,并调用适当内核程序。

(3)故障

故障发生时,处理器将控制转移给故障处理程序。如果能够修正这个错误情况,就将控制返回到引起故障的指令,从而重新执行它,否则处理程序回到内核中的abort例程,该例程会终止引起故障的应用程序,如图6-4。

图6-4

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oD6gvjCX-1590259653588)(media/c9d55bfd096834d24f78fc5fe2c39760.png)]

故障处理过程

(4)终止

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aKdgIigS-1590259653589)(media/0c594cbf288c5cf840c8e32bc9f4aa31.png)]

终止处理程序从不讲控制返回给应用程序,处理程序将控制返回给一个abort例程,该例程会终止这个应用程序,如图6-5。

图6-5 终止处理过程

6.6.2实际情况下的异常处理

(1)运行过程中按ctrlz

发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程,而并
非结束进程,用户可以使用使用fg/bg操作恢复执行前台或后台的进程。fg命令在前台恢复执行被挂起的进程。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h8Z6bykT-1590259653591)(media/065f17b46dc38d2a53dc831bc5ad8f12.png)]

图 6-6处理过程按ctrl+z截图

如图6-6所示,处理过程按下ctrl+z,程序会中断,输入ps可以看到存在hello进程。

输入pstree查看进程树如图6-7:

图6-7(1)按下ctrl+z后的进程树

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iG3IvaXh-1590259653593)(media/a07ea372d743eda6774ef64399cea03a.png)]

图6-7

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bvUgsHNt-1590259653594)(media/4d97bef37ca6456efa254c4049bcff6c.png)]

(2)按下ctrl+z之后的进程树

图6-8

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ozt1DeS-1590259653595)(media/e66322cd279d4254ca65f67f0b3fcf14.png)]

输入jobs之后的截图

./media/image67.png

输入jobs命令,可以看到显示hello程序的状态为已停止,同时也显示输入的4个参数。

图6-9 输入fg命令的截图

输入fg,进程会从停止处继续执行到程序结束。

图6-10

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wTrTdJwF-1590259653597)(media/ceb0d67696243ceb6df193bc0ee4d621.png)]

输入kill之后的截图

kill 9 PID命令可以杀死hello程序。

(2)运行过程中按ctrl+c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1pQ3FSkX-1590259653599)(media/1cbd27a79b9933bab0df377bbd4bd507.png)]

运行过程中,发送 SIGTSTP 信号给前台进程组中的所有进程终止进程。

图6-11 按ctrl+c之后的截图

可以看到在运行过程中按ctrl+c程序终止,输入ps命令不存在hello进程。

(3)运行过程中按回车

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NVS5D0NJ-1590259653602)(media/83e17eb6a17eb50ff703b9a8db3255e1.png)]

图6-12 运行过程中按回车

可以看到运行过程中按回车,程序并没有挂起与中断,只是输出时多了换行。乱按也是如此,只是输出多了乱按的内容。

6.7本章小结

本章主要介绍了进程管理的相关概念与内容。首先介绍了进程管理的概念与作用,接着介绍了shell-bash的概念与作用,然后依次介绍了hello程序的fork、execve、进程执行、异常与信号处理等过程。本章对hello程序执行过程中的逻辑控制流、上下文切换过程、异常类型与处理方法都有了清晰的阐述。

(第6章1分)


第7章 hello的存储管理

7.1 hello的存储器地址空间

逻辑地址:是指由程序产生的与段相关的偏移地址部分。就是hello.o里面的相对偏移地址。

线性地址:地址空间时一个非负整数地址的有序集合。如果地址空间中的整数是连续的,那么它就是线性地址空间。是逻辑地址到物理地址的中间态。

虚拟地址:在一个带虚拟内存的系统中,CPU从一个有N=2n个地址的地址空间中生成虚拟内存,这个地址空间称为虚拟地址空间。如32位CPU虚拟地址为4G,64位CPU虚拟地址为64T

物理地址:加载到内存地址寄存器中的地址,内存单元的真正地址。在前端总线上传输的内存地址都是物理内存地址,编号从0开始一直到可用物理内存的最高端。是指出目前CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。如果启用了分页机制,那么线性地址会使用页目录和页表中的项变换成物理地址。如果没有启用分页机制,那么线性地址就直接成为物理地址了。

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

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

Intel从逻辑地址变换到线性地址需要段式管理,而实现段式管理需要段寄存器和段选择符。有6个16位段寄存器,分别为CS(代码段)表示程序代码所在段,SS(栈段)表示栈区所在段,DS(数据段)为全局静态数据区所在段,其他三个段寄存器ES\GS\FS可指向任意数据段。

段寄存器用于存放段选择符,而段选择符主要包括以下字段

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKnjzW04-1590259653603)(media/80e5d56226e7bd001b8e9849f62c34ea.png)]

图7-1 段选择符各字段结构

当TI=0,选择全局描述符表,当TI=1,选择局部描述符表。

RPL=00,为第0级,位于最高级的内核态,RPL=11,为第三级,位于最低级的用户态,第0级高于第三级。有13位索引,8k个用来确定当前使用的段描述符在描述符表中的位置。

一个逻辑地址由两部份组成,段选择符、段内偏移量。根据段描述符作为下表,到GDT/LDT表查表即可获得段地址,线性地址等于段地址加偏移地址。

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

虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每个字节都有唯一虚拟地址,作为到数组的索引。磁盘上数组的内容被缓存在主存中。磁盘上的数据被分割为块,这些块作为磁盘和主存之间的传输单元。VM系统将虚拟内存分割为称为虚拟页的大小固定的块。每个虚拟页的大小为P=2p字节。物理内存被分割为物理页,大小也为P字节,没有被分配的虚拟页在磁盘上不存在,已缓存的虚拟页被缓存在物理内存。

图7-2虚拟内存作为缓存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aDSAzl7V-1590259653604)(media/bed3ece1c79476e6ed8145eced65977c.png)]

从虚拟地址空间到物理地址空间需要经过地址翻译,地址翻译是一个N元素的虚拟地址空间(VAS)中的元素和一个M元素的物理地址空间(PAS)中元素之间的映射。

MAP:VASPAS ∪ ∅ \cup \varnothing

MAP(A)= A’如果虚拟地址A处的数据在PAS的物理地址A’处

∅ \varnothing 如果虚拟地址A处的数据不在物理内存中

图7-3表示了如何实现虚拟地址到物理地址的映射,CPU中一个控制寄存器,页表基址寄存器指向当前页表。N位虚拟地址包含两部分:一个p位的虚拟页面偏移(VPO)和一个(n-p)位的虚拟页号(VPN)。MMU利用VPN来选择适当的PTE。例如VPN=0,选择PTE0,VPN=1,选择PTE1,以此类推,将页表条目中的物理页号和虚拟地址中的VPO串联起来,就得到相应的物理地址。

图7-3 虚拟地址到物理地址的映射

./media/image73.png

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NlWi0ZcL-1590259653605)(media/0ff33c30d601d95a1d41bd01f63f0611.png)]

TLB是一个小的、虚拟寻址的缓存,其中每一行都保存着一个由单个PTE组成的块。TLB通常有高度相联度,如图7-4,用于组选择和行匹配的索引和标记字段是从虚拟地址中的虚拟页号中提取出来的。如果TLB有T=2t个组,那么TLB索引(TLBI)是由VPN的t个最低位组成的,而TLB标记(TLBT)是由VPN中剩余位组成的。

图7-4 虚拟地址用以访问TLB的组成部分

图7-5表示了MMU如何使用四级的页表将虚拟地址翻译成物理地址。36位VPN被划分为四个9位的片,每个片被用到一个页表的偏移量。CR3寄存器包含L1页表的物理地址。VPN1提供到一个L1PTE的偏移量,这个PTE包含L2页表的基地址。VPN2提供到一个L2PTE的偏移量,以此类推。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pVfQ73VB-1590259653607)(media/83b2ba663f566ba4dcdf260117586fea.png)]

图7-5 四级页表支持下VA到PA的变换

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iDKKfMOi-1590259653609)(media/63966991014c1ebc2bf43e5d11aec19f.png)]

图7-6 Intel i7 高速缓存层次结构

如图7-6所示为告诉缓存层次结构,每个CPU芯片四个核,每个核有自己私有的L1 i-cache,L2 d-cache和L2统一的高速缓存。所有核共享片上L3统一的高速缓存。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s2cld3Nz-1590259653610)(media/c3035323751a3aaa53186c6762e3f369.png)]

图7-7 三级cache物理内存访问

如图7-7所示,Core
i7的三级cache是物理寻址的,块大小为64字节。LI和L2为8路组相联,L3是16路组相联的。支持48位虚拟地址空间和52位物理地址空间。CPU把地址发送给L1,L1为8路,所以S=8,s=3。因为L1块大小为64字节,所以B
= 64,b =
6。标记位t为43位。根据物理地址的s位组索引索引到L1cache中的某个组,然后在该组中查找是否有一行有效位为1并且标记与物理地址匹配。如果有,那么命中命中,从这一行对应物理地址b位块偏移的位置取出一个字节,若不满足上面的条件,则说明不命中,需要继续访问下一级cache,访问的原理与L1相同,若是三级cache都没有要访问的数据,则需要访问内存,从内存中取出数据并放入cache。

7.6 hello进程fork时的内存映射

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

当fork在新进程中返回时,新进程现在的虚拟内存刚好和调用fork时存在的虚拟内存相同。当这两个进程中的任一个后来进行写操作时,写时复制机制就会创建新页面,因此也就为每个进程保持了私有地址空间的概念。

7.7 hello进程execve时的内存映射

Execve函数在当前进程中加载并运行包含在可执行目标文件a.out中的程序,用a.out有效替代当前程序。加载运行过程需要以下几个步骤:

(1)删除已存在的用户区域。删除当前进程虚拟地址的用户部分中的已存

在的区域结构。

(2)映射私有区域。为新程序的代码、数据、bss和栈区域创建新的区域结构。这些新区域都是私有、写时复制的。代码和数据区被映射为a.out文件中的.text和.data区。.bss区是请求二进制零的,映射到匿名文件,其大小包含在a.out中。栈和堆区域页请求二进制零,初始长度为0。

(3)映射共享区域。如果a.out程序与共享对象(或目标)链接,比如标准C库libc.so,那么这些对象都是动态链接到这个程序的,在映射到用户虚拟地址空间中的共享区域内。

(4)设置程序技术器(PC)。Execve做的最后一件事是设置当前进程上下文中的程序计数器,使之指向代码区域的入口点。下一次调度该进程,将从入口点开始。

图7-8表示了加载器是如何映射用户地址空间的区域的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hwLf0WCP-1590259653612)(media/8e107a5dacbb2b46fbdb3fe9f3883ad0.png)]

图7-8加载器如何映射用户地址空间区域

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

DRAM缓存不命中称为缺页。对缺页异常的处理如图7-9所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVtTBbAU-1590259653614)(media/e60eaf6ce64fb74da33aba33a1a06f15.png)]

图7-9缺页异常处理

(1) 处理器将虚拟地址发送给 MMU 。

(2-3)MMU 使用内存中的页表生成PTE地址。

(4)有效位为零, 因此 MMU 触发缺页异常。

(5) 缺页处理程序确定物理内存中牺牲页 (若页面被修改,则换出到磁盘)。

(6) 缺页处理程序调入新的页面,并更新内存中的PTE。

(7) 缺页处理程序返回到原来进程,再次执行缺页的指令。

7.9动态存储分配管理

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

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

虽然可以使用低级mmap和munmap创建和删除虚拟内存的区域,但是C程序仍需要额外虚拟内存时,用动态内存分配器。动态内存分配器维护一个进程的虚拟内存区,称为堆,其结构如图7-10所示。

分配器将堆式位一组不同大小块的集合来维护,每个块就是一个连续的虚拟内存片,要么已分配,要么空闲。已分配的块显示地保留为供内存程序使用,空闲块可用来分配。

分配器有两种基本风格,即显示和隐式分配器,不同之处在于由哪个实体来负责释放已分配的块。

  1. 显示分配器。要求应用显示地释放任何已分配的块,例如malloc程序包就是显示分配器。

  2. 隐式分配器。要求分配器检测一个已分配块合适不再被程序使用,那么就释放。

Malloc函数返回一个指针,指向大小为至少size字节地内存块,这个块会为

可能包含在这个块内地任何数据对象类型做对齐。如果malloc遇到问题,那么返回NULL,并设置errno。Malloc不初始化它返回的内存。

动态内存分配器如malloc可以通过使用mmap和munmap函数,显式地分配和释放堆内存。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Owkqeqgc-1590259653616)(media/194af41ec7d8890a06218c404dcce29b.png)]

图7-10 堆

图7-11表示了malloc和free分配和释放块地过程,每个方框代表一个四个字节地字,有无阴影地块分别对应已分配块和空闲块。

程序请求4字块,则从空闲块地前部切出一个4字的块,并返回指向这个快的第一个字的指针。

7-11(b)程序请求一个5字的块,则从空闲块的前部分配一个6字的块。

7-11(c)程序请求一个6字的块,malloc就从空闲块的前部切出一个6字的块。

(d)程序释放在(b)中分配的6字的块。调用free之后,p2指针仍旧指向被释放的块。

(e)程序请求一个2字的块。这种情况下,malloc分配在前一步中被释放了的块的一部分,并返回指向这个新块的指针。

不正确使用分配器将导致碎片等问题。任何实际的分配器都需要一些数据结构来区别块边界。隐式空闲链表就是一种。使用时需要放置已分配的块、分割空闲块、如果不能找到空闲块,则需要合并内存中物理上相邻的空闲块,若还不足够大则需要获得额外堆内存。最后分配器要实现带边界标记的合并。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MRCxRJoF-1590259653617)(media/fd6bd50372fdc596a56961aa28f0df30.png)]

图7-11 malloc和free维护堆的过程

7.10本章小结

本章主要介绍了hello的存储空间的一些概念。首先介绍了逻辑地址、线性地址、虚拟地址、物理地址的相关概念,接着阐述了如何实现段式管理下逻辑地址到线性地址的变换以及页式管理下虚拟地址到物理地址的变化。并且进一步介绍了TLB与四级页表支持下虚拟地址到物理地址的变换和三级cache下物理空间的相关内容。同时,在了解了存储空间之后再次解释了hello的fork和execve的过程。

最后介绍了缺页异常的处理方法以及动态内存分配的策略。

(第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接口及其函数

将设备优雅地映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,称为Unix
I/O。

函数:

  • 打开和关闭文件

open()and close()

  • 读写文件

read() and write()

  • 改变当前的文件位置 (seek)

指示文件要读写位置的偏移量

lseek()

8.3 printf的实现分析

从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall.

字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。

显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。

8.4 getchar的实现分析

异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。

getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。

8.5本章小结

本章简要介绍了Linux的IO设备的管理方法和UnixIO接口及其函数,并简单分析了printf函数和getchar函数的实现过程。

(第8章1分)

结论

(1)hello.c 源程序经过预处理器(cpp)预处理生成hello.i文本程序。

(2)hello.i在编译器(cc1)编译后形成hello.s汇编程序。

(3)汇编程序经过汇编器(as)处理生成hello.o可重定位目标程序。

(4)hello.o和printf.o经过链接器链接生成hello可执行目标程序。

(5)然后当开始执行hello,操作系统内核通过上下文切换与进程控制等为hello形成子进程,并处理执行过程中可能遇到的一系列异常。

(6)hello
中的程序从逻辑地址经过段式管理映射到虚拟地址,又经过虚拟地址映射到物理地址。

(7)并且经过I/O管理与接口等被执行完成。

对于一个很简单的程序来说需要经过复杂的系统设计,要想实现出好的系统设计需要对计算机的系统非常熟悉,从程序的生成过程到执行过程,都有有一个全面的认识,同时还需要考虑到程序在执行过程中可能出现的问题,如各种异常等等以及处理这些异常的方法与策略。与此同时,要实现好的系统设计也需要考虑到如何节约计算机的空间等资源,避免资源浪费,如对于进程控制,就可以杀死不需要的进程。总之要想实现优秀的系统设计,需要对计算机底层的知识非常了解。

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


附件

hello.c 源程序

hello.i 预处理之后地程序

hello.s 汇编程序

hello.o 可重定位目标程序

hello 可执行目标程序

hello.elf hello.s的elf文件,方便查看与分析

hello2.elf hello.o的elf文件,方便查看与分析

(附件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分)
的程序从逻辑地址经过段式管理映射到虚拟地址,又经过虚拟地址映射到物理地址。

(7)并且经过I/O管理与接口等被执行完成。

对于一个很简单的程序来说需要经过复杂的系统设计,要想实现出好的系统设计需要对计算机的系统非常熟悉,从程序的生成过程到执行过程,都有有一个全面的认识,同时还需要考虑到程序在执行过程中可能出现的问题,如各种异常等等以及处理这些异常的方法与策略。与此同时,要实现好的系统设计也需要考虑到如何节约计算机的空间等资源,避免资源浪费,如对于进程控制,就可以杀死不需要的进程。总之要想实现优秀的系统设计,需要对计算机底层的知识非常了解。

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


附件

hello.c 源程序

hello.i 预处理之后地程序

hello.s 汇编程序

hello.o 可重定位目标程序

hello 可执行目标程序

hello.elf hello.s的elf文件,方便查看与分析

hello2.elf hello.o的elf文件,方便查看与分析

(附件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分)

你可能感兴趣的:(课程作业)