@

计算机系统

大作业

题 目 程序人生-Hello’s P2P
专 业 计算机类
学   号 L190201101
班   级 1903005
学 生 朴仁洪  
指 导 教 师 史先俊

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

关键词:关键词1;关键词2;……;

目 录

第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:在Linux中,hello.c经过cpp的预处理、ccl的编译、 as的汇编、 ld的链接, 成为目标程序hello。 从 shell 输入启动命令, shell 将生成子进程 。 然后hello从程序变为程序。
020: shell 以映射方式显示此进程的 execve. 虚拟内存 。 在程序入口处, 程序开始装入物理内存, 并进入 main 函数运行目标代码 。 CPU 为运行中的 hello 时间套餐执行逻辑流媒体 。当程序运行时, Shell 父进程将回收 Hello 进程, 从内核中删除相关数据结构 。
1.2 环境与工具
硬件环境:X64 CPU;2GHz;2G RAM;256GHD Disk 以上
软件环境:Windows7 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位
开发与调试工具:gcc,vim,edb,readelf,HexEdit
1.3 中间结果
hello.i hello.c预处理之后文本文件
hello.s hello.i编译后的汇编文件
hello.o hello.s汇编之后的可重定位目标文件
hello 链接之后的可执行目标文件
hello.out hello反汇编之后的可重定位文件
1.4 本章小结
本章主要介绍hello的p2p、020过程,并介绍本次实验信息:环境、中间结果以及大体上hello程序从c程序hello.c到可执行的目标文件hello的大致过程。 。

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

预处理概念:预处理器cpp根据以字符#开头的命令修改原始的C程序,将引用的所有库展开合并成为一个完整的文本文件。
预处理级别角色 :

  1. 预处理的处理器根据#if, #ifdef等编译命令和以后的条件,包含或排除原程序的一部分。 将常规的除外词组转换为空行 。
  2. 编译处理条件命令
    条件编译指令 : #ifdef, #ifdef, #else, #elif, #endif等. 这些假指令的引入,使程序员得以定义为不同的矩阵,从而决定编译程序要处理哪些代码。预先编译过的程序会根据相关文件过滤不必要的代码 。
  3. 令如#include "FileName"或者#include 等。 此命令将全部头文件的定义放入输出文件, 以便编译程序能够处理。
    4.处理特殊符号
    预编程序可以识别一些特殊符号。 例如,源代码中出现的线标是当前行号(十进制数),FILE是目前编译的C源程序的名字。预先编译过的程序将被来源于源程序的矩阵替换为合理值 。

2.2在Ubuntu下预处理的命令
gcc hello.c -E -o hello.i

2.3 Hello的预处理结果解析

2.4 本章小结
介绍了用定义的宏观符号替换符号、导入到头文件的内容、根据命令的选择性编译等预处理的相关概念及其处理。

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

编译的概念:编译器将包含汇编语言程序的文本文件翻译成hello.s。输入高级编程语言的源头顺序,输出用汇编语言或机器语言标记的目标程序。 这个过程被称为编译,同时起到编译的作用。
编译程序的基本功能是将源代码(高级语言)翻译成目标程序。除基本功能外,还具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、各语言应用及人际网络等重要功能。
3.2 在Ubuntu下编译的命令
gcc -S hello.i -o hello.s

3.3 Hello的编译结果解析

.file:声明源文件
.text:代码节
.section:
.rodata:只读代码段
.align:数据或者指令的地址对其方式
.string:声明一个字符串(.LC0,.LC1)
.global:声明全局变量(main)
.type:声明一个符号是数据类型还是函数类型
3.3.1数据
1.字符串
程序中有两个字符串,由上图可知,这两个字符串都在只读数据段中,分别如图所示:

3.main函数
参数 argc 作为用户传给main的参数。也是被放到了堆栈中。

4.各种立即数
立即数直接体现在汇编代码中

5.数组:char *argv[]
hello.c的唯一数组是main函数的第二参数,每个参数都是指向文字的指针。在堆栈- 32 (% rbp) 中保存初始地址, 并在 printf 中两次调用参数 。

红色:数组argv的存放的位置:-32(%rbp)
蓝色:分别获取argv[1]和argv[2]的地址
3.3.2.全局函数

  • int main (int argc,char *argv[]){

从 hello.c 可以看出 hello.c 描述并编译了全局函数 int main( intargc, char*argv[])后,将main函数中使用的字符串常量也保存到数据区域。

3.3.3赋值操作
程序的副值操作主要如下:i=0的副值操作主要在汇编代码中使用mov指令进行,但根据数据类型的不同,有多种不同的后缀。
movb:一个字节
movw:两个字节
movl:四个字节
movq:八个字节

3.3.4算数操作

hello.c中的算数操作有:i++,由于是i是int类型的,因此汇编代码只用addl就能实现其他的操作有

lead S,D D=&S
INC D+=q
DEC D D-=1
NEG D D= -D
ADD S<D D=D+S
SUB S,D D=D-S

3.3.5关系操作
(1) argc! = 3; 判断条件句子的条件: 编译 argc! = 3时,本命令语如下: cmpl $3,-20 (% rbp ) , 此命令包含代码设置, 并判断是否需要分区 。

(2)i<8, hello.c以判断循环为条件,在汇编代码中编译如下: 计算cmpl $7,-4(% rbp), i-7后设置条件代码, 准备在下一个 jle 利用条件代码跳跃。

3.3.6控制转移指令
汇编器有首先设定条件代码,沿着条件代码移动的控制命令。 (1)判断i是否为3。 如果 i 是 3, 则不执行 if 语句 。 否则, 运行 if 语句 。 对应的汇编代码是

(2) for (i=0;i<8;i++). 每次比8小i满意度因此转移到了循环语句应该判断。 汇编代码如下。

第一个红色:首先i赋初值0,然后无条件跳转至判断条件的代码中,即.L3.
第二个红色:判断i是否符合循环的条件,符合直接跳转至.L4,也就是循环体的内部.

3.3.7函数操作
调用函数时有以下操作: (假设函数 P 调用函数 Q)
(1) 传递控制: 在进行过程 Q 时, 您必须设置以程序柜台 Q 开头的代码的起始地址 。 然后返回时, 程序柜台必须设置在 Q 后面的命令作为 P 调用的地址 。
(2) 数据传递:P应能为Q提供超过一个数据每个参数, Q 必须允许一个值返回 P 。
(3) 内存分配和释放: Q 启动时可能需要的部分变量分配空间 。 在回去之前要先放置这些空间。
hello.C中涉及的函数操作如下:
main 函数 , printf,exit,sleep , getchar 函数
main 函数的参数是 argc 和 ar digv; 两次 printf 函数的参数正确是两个字符串 。
exit因子为1、sleep函数参照数为argv[3]。
函数返回值保存到% eax 寄存器 。

3.3.8类型转换
hello.c所涉及的类型转换是:argv[3];将字符串类型转换为正数类型的其他类型转换;int、float、double、short、char之间的转换。
3.4 本章小结
本章主要讲述了编译阶段中编译器如何处理各种数据和操作,以及c语言中各种类型和操作所对应的的汇编代码。通过理解了这些编译器编译的机制,我们可以很容易的将汇编语言翻译成c语言。
第4章 汇编
4.1 汇编的概念与作用
汇编( as) 将汇编翻译成机器语命令语, 并将这些命令以重新找到目标程序的形式打包。 保存到 o 目标文件中。 o 文件是包含命令编码的一份二进制文件。
4.2 在Ubuntu下汇编的命令
gcc hello.s -c -o hello.o

4.3 可重定位目标elf格式
(1) ELF Header : 用 命令 : readelf - h hello.o ,
ELF Header: 以 16B 序列 Magic 启动, 说明 Magic 创建此文件的系统的字体大小和字节顺序 。 ELF 头条的剩余部分包括链接器语法分析和#标题显示对象文件的大小、目标文件的种类、机器类型、字节头桌的文件偏移、节点头桌的项目大小和个数等。

根据头文件的信息,可以知道该文件是可重定位目标文件,有13个节

  1. Section Headers:命令:readelf -S hello.o
    Section Headers: 节点Headers: 包含每个节点的意义, 包括节点类型、 位置、 大小等信息。 您可以重新配置目标文件, 因此各节从 0 开始重新配置 。从文件头获取节点信息后, 使用节点偏移信息获取文件中节点所占据的空间大小, 代码可执行, 但无法写入, 只能执行数据段落和读取数据段落, 读取数据段落也无法写入。

(3)查看符号表.symtab :命令readelf -s hello.o
. symtab: 保存应用程序中定义和引用的函数和全局变量的信息 。name 是符号名称 。 Value 针对符号模块, value 符号比对象节的开始位置倾斜。 可执行目标文件的绝对地址 。size是目标的大小,type是数据或函数。Bind 字段显示符号是本地还是全局 。

初始化节点 :. text 节点位置列表 。 当目标文件和链接将其它文件组合起来时, 您必须更改 。
初始化节. rela.text 的符号信息 :

Offset: 包含要更改的引用节的偏移Info: symbol 和 type 两个部分 。 symbol是前四节拍,type是后四节拍,
symbol: 更改了标志, 指向了它们的符号,
type: 初始化类型
Type: 链接提示您如何修改新程序 。
Attend: 有符号常数 。 部分重整行用于更改引用值Name: 重命名目标 。
4.4 Hello.o的结果解析
objdump -d -r hello.o 分析hello.o


汇编的代码和hello.s比较的结果,汇编的命令语没有区别。 只是汇编代码不仅标注了汇编代码,还标注了机器代码。 机器语言软件是李镇洙机器的命令语集合,是纯粹的李镇洙数据所表现的语言,是计算机能够正确识别语言。机器指令由操作代码和操作数组成,汇编语言是直接表现CPU动作的形成,是最接近CPU运转原理的语言。每个汇编操作代码都可以用机器的二进制数据来表示,进而可以使所有的汇编(操作代码和操作数)和二进制语言建立一个个映射的关系,因此可以将汇编转换成机器语言。

(1)分支转移: 汇编的移动指令是。 L3, 不是短路,而是汇编时容易写出的帮助,因此汇编语言后就不存在了。

(2)函数调用: 如果函数在.s 文件中呼出, 函数名称将保持原样, 反向编程程序中的 call 目标地址是当前命令 。这是因为从 hello.c 呼出的函数是共享库中的函数, 因此只能通过动态链接来执行, 当汇编成为汇编语言时, 对于这个不确定的函数呼出, call 命令的相对地址设置为 0, 并在下一个命令中设置下列命令 。 在 rela.text 栏目中再次添加静态链接, 然后等待下一个链接 。
4.5 本章小结
本章将hello.s作为汇编,分析了可以重新设定hello.o对象文件的ELF头、切豆腐、符号表和可以重新设定的节点,比较hello.s和hello.o悖论代码的不同之处,从汇编语言到机器语言一一分析了映射关系。

第5章 链接
5.1 链接的概念与作用
链接是将多种代码和数据片段收集并组合成一个单一文件的过程,可将文件加载(复制)并运行到内存中。链接在编译时,即源代码被编译为机器代码时,加载时,程序被加载到内存上运行时,甚至运行时,应用程序也可以被执行。链接将在一个名为链接器的程序中运行 。链接允许分离编译。
5.2 在Ubuntu下链接的命令

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

ELF Header: hello 的文件头与hello.o文件头不同之处在于,如下图所示,Type类型表示EXEC中hello是可执行的文件。 有25个


节头部表Section Headers: Section Headers 包含 hello 中的所有节点信息的大小 Size 和程序中的偏移量 Offset, 因此可以根据栏目 Headers 中的信息, 确定每个节点所占的区域( 起始位置、 大小) 。其中Address是程序导入虚拟地址的起始地址 。
在这里插入图片描述

符号表.symtab

5.4 hello的虚拟地址空间
使用 edb 加载 hello 查看本进程的虚拟地址空间信息, 并对比 5.3 进行说明。

从edb来看,hello的虚拟地址空间为0x401000,终止和0x401ff0 。

5.5 链接的重定位过程分析
使用命令:objdump -d -r hello >hello.out,获得hello的反汇编代码.
分析hello和hello的差异,说明链接过程。可以发现以下不同之处。

(1)hello 逆向代码有确定的虚拟地址。 换句话说,已经完成了重新定位。 hello.o 反向通讯代码中代码的虚拟地址均未完成重新装配为 0 。

(2) Hello 译成汇编的代码中有许多节数和许多函数的汇编代码。 这些寺庙都有一定的东西。功能和含义列举了一些节义。


5.6 hello的执行流程

5.7 Hello的动态链接分析
动态链接的基本思想是, 根据模块分离程序, 当程序运行时, 不像静态链接那样将所有程序模块连接到可执行文件, 而是连接到可执行文件 。虽然动态链接在程序执行时延迟了链接,但在创建可执行文件时(制作可执行文件和制作可执行程序时注意不同的概念),应该使用动态链接库。例如, 在创建可执行程序时, 发现引用了外部函数, 此时会检查动态链接库, 并发现该函数名为动态链接符号。 在这种情况下, 可执行程序将不再重置此符号, 而是当装载此符号时再进行 。

在呼叫共享库函数时,编译器无法预测该函数的运行地址,因为定义该函数的共享模块在运行时可以被加载到任意位置。正常的方法是生成引用该引用的在位记录,并在程序被导入时由动态链接进行解释。GNU 编译系统使用延迟绑定(lazybinding) , 直到您第一次调用程序地址绑定 。

延迟绑定是通过GOT和PLT完成。GOT是数据区块的一部分,PLT是代码区块的一部分。两票的内容如下。

PLT:PLT是拥有16字节代码的组合。PLT[0]是动态链接器移动的特殊项目。调用到可执行程序的所有库函数都有PLT项目 。各项负责呼叫具体函数。

GOT:GOT是有8字节地址的组合。与PLT协同使用时,GOT[O]和GOT[1]包含动态链接解释函数地址时所使用的信息。GOT[2) 是1d-linux.so模块中的动态链接入口处。其余各项目对应于运行中处理的函数。每个项目都有匹配的PLT项目 。

根据Hello ELF文件,GOT起始表位置为0x404000。 如图 :

5.8 本章小结

本章介绍了链接的概念和作用,详细介绍了hello.o如何成为可执行的目标文件,详细介绍了hello.o的ELF形式和各节的意义,分析了hello的虚拟地址空间、重置进程、运行进程和动态链接过程。苦尽甘来,算是我们的hello诞生了

第6章 hello进程管理
6.1 进程的概念与作用
进程是运行中的程序的实际案例 。 每个进程都有各自的地址空间 。 通常包含文本区域、 数据区域和堆栈 。文本区域存储处理器运行的代码、 数据区域存储变量和进程运行期间使用的动态分配内存、 堆栈区域存储有活跃的命令和本地变量 。

作用:流程为用户提供以下假设:
(1)我们的程序似乎是系统中目前运行的唯一程序。 我们的程序好像是独家使用的处理器和内存。
(2) 处理器似乎不间断地执行我们程序的命令。 我们程序的代码和数据似乎是系统内存中唯一的对象。
6.2 简述壳Shell-bash的作用与处理流程
在 Linux 系统中, Shell 是一个由用户运行其他程序的互动程序。 ( 运行于用户状态的命令行解析器)

解析和执行用户命令是基本功能,重复以下处理过程。
(1) 终端程序读取用户输入键盘的命令行 。
(2) 分析命令行字符串, 获取命令行参数, 并构成要传递给 execve 的 argv 向量
(3) 确定第一条( 第一条、 0条) 是否内置命令行参数的 shell 命令
(4) 如果不是内部命令, 请装入 fork 创建新进程/ 子进程 。
(5) 在子进程中运行 execve () 作为从第二级获取的参数 。
(6) 如果用户没有请求启动后台( 命令结束 & 编号不存在) , shell 将会 wai( 或 wait… 等待任务结束后返回 。
(7) 如果用户请求后台运行( 命令末端有 & 号) , 则返回 shell 。
6.3 Hello的fork进程创建过程
终端程序调用 fork 函数创建子进程 。 子进程与父进程相同, 但创建包含代码、 段落、 数据段落、 共享库和用户堆栈的独立副本 。子进程将导入与父进程所有文件描述符相同的副本 。 当父进程和子进程不同时, PID 则不同 。父进程和子进程是同时运行的独立进程, 您可以任意执行内核控制流量的命令 。当子进程运行时, 父进程的默认设置将等待子进程完成 。

我们的hello。/hello L190201101 输入 1,首先解析 Shell 输入的命令。 由于不是内置的 shell 命令, shell 运行 fork 创建子进程 。
6.4 Hello的execve过程
当子进程创建时, 子进程会从当前子进程上下文载入 exceve 函数, 并运行 hello 程序 。 装入并运行下一步 。

(1) 删除已存在的用户区域 。删除当前进程虚拟地址的用户部分存在的区域结构 。
(2) 在个人区域进行映射。新建应用程序的代码、 数据、 bss 和堆放区域的新区域结构 。所有这些区域结构都是私人的,写的时候都是复印的。虚拟地址空间的代码和数据区域将被映射到 Hello 文件的 .txt 和 .data 区域 。bss 区域请求二进制 0 。 地图匿名文件。 那个大小包含在Hello文件里。堆栈和堆栈区域也请求初始长度为0的二进制数 。
(3) 地图共享区域。如果hello 程序与共享对象相连, 例如标准 C 库 libc.so 所有对象都将被动态地连接到该程序中, 并反映到用户的虚拟中。地址空间的共享区域 。
(4)设置程序柜台(PC)。exceve最后做的就是将当前进程上下文中的程序柜台设置为指向代码区域的入口。调用此进程从这个入口开始实行。Linux可根据需要更换代码和数据页面。
6.5 Hello的进程执行
进程提供给程序的抽象 :
(1) 独立逻辑控制流媒体提供假象,就像我们的流程被独家使用一样
(2)个人地址空间就像我们的程序独家使用CPU内存一样提供虚拟空间。
hello 进程的运行具有依赖性, 是在程序提供的抽象基础上抽象说明操作系统提供的流程:

逻辑控制流 :: 一系列程序员数字PC的值序列称为逻辑控制流。 进程将交替使用处理器 。 在同一个处理器中 。在核心中各进程运行部分流媒体后先占用(暂时结束)并运行其他进程。

并发流:逻辑流的执行时间与其他流重叠,成为并发流,这两个流并发流。多条流媒体同步运行的普通弦象并发。

时间集: 进程执行控制祭品的一部分叫做时间篇。

个人地址空间:提供假象,好像每个流程都垄断使用流媒体系统地址的空间。一般来说,与该空间的某一个地址连接的存储字节不能被其它程序读写,从这个意义上来说,地址空间是私有。。

用户模式和内核模式 :: 使用描述当前进程所具有的特权的寄存器两种方式。当未设置模式节点时, 进程是用户模式 。 在用户模式下, 不允许执行命令, 不允许 。引用地址空间内内内核的代码和数据 。 您可以在设定模式位置时用内核模式运行进程 。收集所有命令, 允许您访问系统中的内存位置 。

上下文句:上下文句是内核。重新启动以普通寄存器、副点寄存器、程序柜台等抢占的进程。由用户堆栈、状态寄存器、内核堆栈及各种内核数据结构等对象值构成。

▦上下文转换:内核选择一个,新流程运行后内核调整流程。在内核上运行新进程后抢占先机当前进程使用一个名为上下文转换的设备, 移动到要控制的新进程 :

  1. 保存上一个进程上下文
  2. 正在恢复保存新恢复进程的下一篇文章,
  3. 将控制传达给新的恢复下面和下面的文本转换完成过程 。

现在我们再次实行hello程序,如果程序呼出execve函数,就可以从以上分析中看出流程是hello。程序分配了新的虚拟地址空间, 并且已经与 hello. txt … 虚拟分配 data 节点 。地址空间的代码区和数据区。在用户模式下运行第一个 hello 。 输出 hello L19020111 park, 以及 hello 调用 sleep 函数后, 当进程陷入内核模式时, 内核将无所作为, 直到 sleep 函数调用结束, 请求休眠以将当前进程从运行队列中导出。进入队列, 计时器开始计时, 内核调整上下文 。 当您将当前进程的控制权移交给另一个进程时, 当计时器到达时, 它们就会进入内核 。运行中断处理, 在队列中重新将 hello 进程移至运行矩阵 。如果进入准备状态,Hello Project可以继续控制自己的逻辑流程。
当hello呼叫getcha时,从实际落地到运行,输入流在stdin的系统呼叫read、hello之前运送的行用户模式、read呼叫后掉入内核,内核的陷阱处理程序在键盘缓冲器中请求的块的DMA传送,在键盘缓冲器中用内存传送数据后,中断处理器。这时候进入内核模式吧。内核运行上下文并切换到其它进程 。当数据从键盘缓冲区传送到内存时, 内核会从另一个进程返回 hello 进程 。

6.6 hello的异常与信号处理
Hello节目可能出现异常。
中断: 运行 Hello 程序时, 外部 I/O 设备可能出现异常 。

陷阱:陷阱是故意的,是执行的。命令结果表明,哈洛在执行sleep函数时出现上述异常。

故障:在运行 hello 程序时,可能会发生页面缺陷的错误操作。

退出: 退出时不可恢复, hello 运行中可能出现 DRAM 节点损坏的编码错误 。

出现异常时发送信号, 比如说有缺页Beat 由 OS 向 用户发送 SIGSEGV 信号, 并由 错误退出用户进程 。

(2) 因键盘的各种操作引起的异常

6.7本章小结
本章重点分析说明程序的定义和作用, 说明壳牌的一般流程和作用, 使用fork打造新流程, 使用execve函数执行hello、 hello的流程, 以及hello的理想和信号处理。

第7章 hello的存储管理
7.1 hello的存储器地址空间
逻辑地址: 程序编译后显示在汇编代码上的地址 。逻辑地址用于指定操作数或指令的地址 。在单段标识符中显示指定段落相对地址的篇数 。

线性地址:也叫虚拟地址,是与逻辑地址相似且不现实的地址。 如果逻辑地址转换为对应硬件平台的模块,那么线性地址就是对应硬件的存储器。调换原址。

虚拟地址: 即线性地址 。

物理地址: 查找内存芯片中使用的单元 。 对应于连接到处理器或 CPU 的总线 。通过直接将物理地址插入机器的存储器本身可以理解,从0字节开始可以一直查看存储器。用最大空量打字节号的代数组被称为物理地址,但实际上只是硬件提供给软件的图像,而寻找存储地址则有所不同。因此,这是"与住所巴士相适应的"。虽然更合适,但是不考虑物理问题,如果考虑寻找地址的方式,可以接受物理地址和物理内存一一对齐。也许错误的理解更有利于形而上的抽签。
7.2 Intel逻辑地址到线性地址的变换-段式管理
段落标识符: 段落内由两个移动量构成的逻辑地址 。据说,断识别者是16位长的断选择者。前13位是索引号。后面的3位包括显示代码寄存器、堆栈寄存器还是数据寄存器的硬件细节。

索引编号是" 段落描述符( segment descriptor) " 的索引 。 段落说明者具体说明段落。将段落说明字分组为"段落说明字表 " 。 在段落标识符前13位可从段落说明符中找到具体内容。丹妙寺,这句话很重要,说明单标识字的具体作用,丹妙寺一节由8字节组成。

Basefield是包含段落第一个字节的线性地址,即表示一段起始位置的线性地址。所有流程都是自己的,即"LDT"等局部、局部、局部、局部、局部说明者(GDT和何时、何时、何时、何时使用LDT?这出现在段落选择者的 T1 字段 。 =0、GDT、=1 将内存内的地址和大小存储在CPU的gdtr控制寄存器中,而LDT则存储在ledtr寄存器中。

首先,给定一个完整的逻辑地址[段选择符:段内偏移地址],
1、看段选择符的T1=0还是1,知道当前要转换是GDT中的段,还是LDT中的段,再根据相应寄存器,得到其地址和大小。我们就有了一个数组了。
2、拿出段选择符中前13位,可以在这个数组中,查找到对应的段描述符,这样,它了Base,即基地址就知道了。
3、把Base + offset,就是要转换的线性地址了。
7.3 Hello的线性地址到物理地址的变换-页式管理
从教科书的知识点可以看出,从线性地址(虚拟地址VA)到物理地址(PA)的转换是通过页面实现的。支付机制将虚拟地址存储空间分为支付空间。

在这里,我们不考虑TLB和传销页面。这将在下面讨论。

使用虚拟地址时, CPU 生成虚拟地址并访问主内存 。 此虚拟地址在发送到内存前将被转换为合适的物理地址 。将虚拟地址转换为物理地址称为" 知" 。地址翻译需要CPU硬件和操作系统之间的紧密合作。在 CPU 芯片中使用名为 MMU 的硬件, 利用 主存储的搜索表动态翻译虚拟地址 。

虚拟地址是分组索引, 以便在磁盘上保存字节 。 磁盘上的组内容已主要保存 。同时,磁盘的数据被分割成碎片,这些块被用于磁盘和主存储之间的传输单元。 虚拟内存分割为虚拟页面 。物理内存被分割为物理页面 。物理页面和虚拟页面大小相同 。

在任意一瞬间,虚拟页面分为三个互不交错的子集。

未分配的: VM 系统未分配的页面
缓存: 当前物理内存的分配页
未缓存的: 当前物理内存未保存的已分配页面

每次将虚拟地址转换为物理地址时,都会查询页面浏览,判断一个虚拟页面完好无损于DRAM的某个地方,如果不在DRAM的某个地方,就可以查询页面浏览项目。磁盘上有虚拟页面 。页面表格将虚拟页面映射到物理页面 。 标签由有效位数和 n 地址字段组成的纸张项数 。有效的D内存条,虚拟页面保存了。 n 位字段是物理页面的起始地址或虚拟页面的起始地址 。
n 位虚拟地址包含两部分: VPO 一个 ppo, 虚拟页面编号 n-pn, 例如 VP 使用 VPN 选择合适的 PTE 。根据N0选择PTE 0.PTE,我们知道虚拟页面的信件。利息, 如果虚拟页面已被缓存, 则连接页面的物理页码和虚拟地址的 VPO 串, 即可获得相应的物理地址 。这里的VPO和POP是一样的。如果虚拟页面没有缓存, 则可能出现留页错误 。将磁盘上的虚拟页面重新载入内存, 并执行导致页面缺失的根进程 。
7.4 TLB与四级页表支持下的VA到PA的变换
如果这种情况发生,每当CPU中虚拟地址被发送到地址管理单元时,MMU必须找到用物理地址翻译虚拟地址的PTE行。MMU为了消除这一作业带来的费用负担,还被称为对PTE的小缓存、翻译用保险杠(TLB)。例如, cpu 需要重新翻译虚拟地址时, 需要发送 vpn 获取虚拟地址 mmu, 需要发送 vpo 节拍获取 l1 缓存 。 例如, 使用 mmu 请求 tlb 的组件, l1 高速缓存可以在一个 vpo 位子上找到一个虚拟的地址组件 。 您可以找到此组的数据显示 。 mpu 存储在 ppppb 的组中 。
corei7 使用四档次。 各有4档次。 这种设计方法基本上减少了内存的需求。 如果1级榜单的pte全部为空,则2级榜单不再存在。 因此,您可以为您的进程节省很多内存。 而且1级榜单要一直放在一个内存里。第四段页的层级结构操作如下:36位虚拟地址由寄存器区分,构成9位底片,每个字段用于每一页表的偏移量。cr3 寄存器中存储有 l1 页的物理起始站址, 此地址是指表格下面和下面的一些信息。vpn1 提供到 l1pet 的移动量 。 此 pte 寄存器是 l2 页表的起始站址 。 包括vpn2到l2pte的移动量分为4个阶段。 从这个角度分等级。
7.5 三级Cache支持下的物理内存访问
物理地址的结构包括组索引CI(下7-12位 ) , 使用该数字进行组索引, 使用组索引找到组索引后组成。假设我们的 cache 使用的是 8 号块, 如果匹配的显示位置 CT(前排 40 位) 是一个成功且查找的块有效位 valid 显示的值为 1 , 则根据数据偏移量 CO(后排 6 位) 取出所需数据并返回。
如果数据未成功匹配或匹配, 则标志为 1 , 则将在下一阶段缓存中查询数据 。 ( L2 Cache-> L3 Cache-> 主页保存) 将搜索到的数据装入 cache 。此时,我们面临着替换谁的问题。通常情况下, 当我们使用常见的简单替换方法查询获得的数据后, 例如, 如果我们映射的组中有大量空格, 则保留到组内; 否则, 组内发生有效的分组冲突时, 决定应用最近最小使用( lfu) 策略, 然后用牺牲块替换。
7.6 hello进程fork时的内存映射
Fork 函数在上面说明过, 在这里只进行简单的重复 。
壳牌通过调用 fork 函数, 创建一个新流程, 可实现进程内核 。 此进程具有新的数据结构, 由内核分配了唯一的 pid 。拥有属于自己的虚拟存储空间,每个数据区域都拥有当前打开的各种文件信息和页面表的原始数据和样本, 用于有效保护流程中的个人数据和信息, 减少对存储的消耗。
7.7 hello进程execve时的内存映射
execve函数在上面已经介绍,在这里只做简单的重复。
execve函数在当前代码共享进程的上下文中加载并自动运行新的代码共享程序可以自动覆盖当前进程的所有虚拟地址和空间, 当前进程中所有虚拟地址的用户都可以删除虚拟和部分空间中存在的代码共享区域和结构, 但不会自动创建新的代码共享进程。新程序在堆栈中拥有相同区域的 pid 。此后, 为运行新程序的用户共享代码、 数据、 bss 和所有堆栈的区域结构创建新的共享区域和结构。 通过链接将其称为新的私有代码共享区域,所有这些新代码共享区域都可以在执行中复制到个人或个人使用中。此程序与当前共享的 libc.so 链接, 您可以通过映射链接在该代码共享程序的上下文上动态显示, 然后通过映射链接连接到用户的虚拟地址和部分空间区域的其他共享代码区域。为了配置新的程序计数器, execve 函数最后需要做的就是自动设置当前代码共享进程的上下文中的程序计数器, 使其成为指向所有代码共享区域的入口( 即_start 函数 ) 。
7.8 缺页故障与缺页中断处理
STEP 1:CPU生成虚拟地址并传送到MMU。
STEP 2: 请保存地址管理单元生成 PTE 地址, 并获得高速缓存/ 地址 。
Step 3: 高速缓存/ 移动到 MMU 。
Step4: PTE的有效节点为零, MMU出现异常, 传递CPU控制在操作系统内核的纸质异常处理程序
Step 5: 如果没有处理页面的程序决定物理内存的牺牲页 。 如果修改了页面,请改为磁盘。
Step 6: 未处理页面时, 更改新页面并更新内存中的 P 。TE .
Step 7: 缺陷处理程序将地址恢复到原来的缺陷处理流程, 再次执行处理命令, cpu 以便在主仓库中漏页, 并返回地址 。处理器 mmu. 由于程序中的虚拟页面目前已经完全保存了发送物理性虚拟内存, 处理器将再次命中, 主内存会将请求的字符串的返回地址发送到虚拟内存处理器中。
7.9动态存储分配管理
动态存储器分配器是堆放程序的虚拟存储器领域。 虽然系统之间的细节不同, 但不失一般性 。 堆栈将从未初始化的数据区域开始, 并上升到更高的地址 。 对于整个进程, 内核将保持变量 brk, 并指向堆栈的顶部 。
分配器将堆栈视为不同大小的积木的集合来维持。 每个区块被分配或空置 。 分配的块将被用作进纸程序 。 多余的积木可以分配。 空积木可用 。 保持充裕的积木, 直到使用 。 分配的积木已经分配了。 分配的块保持分配的状态 。放出,这种放出是应用程式化操作,或者存储分配器自己隐式化操作。
分配器有两种基本风格。 两种风格都要应用显式分配。 它们的不同之处在于, 哪个实体应该负责释放分配的块
图形分配器( explicit allocator) :
要求将分配的块导出到显式位置 。 例如,C标准库提供被称为malloc套餐的显式分配器。 C 程序通过调用 malloc 函数分配块, 调用 free 函数输出块 。 C++ 的 new 和 delete 动作表与 C 的 malloc 和 free 相同 。
implicit allocator:
要确定分配器中分配的块是否在程序中使用该块 。 隐性分配器又称垃圾收集器( garbage collector ) , 将未使用的积木自动释放的过程称为垃圾收集器( garbage collection ) 。 例如,Lisp、ML或Java等高级语言为了释放分配的区块,依赖于垃圾收集。
一个块由一个字的头部、有效载荷和尽可能少量的补充组成。 头部编码了这块块的大小和已经分配的还是空的。 如果我们强加两个字的排序约束条件,区块大小总是8的倍数,区块大小的最低3位总是0 因此,我们只需要29个内存大小。编码高位, 其余3位 。 此时, 使用最低的位数( 已分配的位数) , 看看是分配的还是空的位数 。
显示剩余链接 :
更好的方法是将空块变成某种形式的数据结构 。 根据定义, 由于程序不需要空块的本体, 因此实现该数据结构的指针可以保存到空块的本体中 。 例如, 堆栈可以创建双向空的链接表 。 pred( 灯泡) 和 succ( 继承) 指南 。
7.10本章小结
本章主要分析了hello程序运行时虚拟地址的变化,分析了适用于hello应用程序的虚拟存储地址空间,分析了虚拟地址、线性地址和虚拟物理线性地址之间的相互转换、纸张命中和纸张命中、动态快照手表作为纸张的高速缓存和纸张、动态存储管理的动作、fork启动内存中断和映射、exec。这些Cashi的基础知识帮助我们制定对高速Cashi更加友好的程序代码和一些高速Cashi的优化解决办法,加快我们的程序运行。

第8章 hello的IO管理
8.1 Linux的IO设备管理方法
Linux 文件是 m字节的行 :
B0 , B1 , B2……Bm

所有 IO 设备( 例如网络、 磁盘、 终端) 模型被文件化, 所有这些都输了 。输入或输出以读写相应文件的方式运行。 将该设备优雅映射到文件的方式允许名为 Unix I/O 的 Linux 内核被装入 。 此为所有输入和输出以读写相应文件的方式运行 。

  • 设备模型化: 文件
  • 设备管理: unixio 接口
    8.2 简述Unix IO接口及其函数
    Unix I/O 界面 :
    打开文件
    ( 1) 。应用程序打开内核的文件, 提醒您, 内核必须旋转小非整数, 以便访问 I/O 设备 。 这个叫说明者。 写入内核打开文件的全部信息 。
    (2) Shell 创建的每个进程都有3个打开的文件: 标准输入、 标准输出、 标准错误 。
    (3) 更改当前文件位置: 对于所有打开文件, 内核保留了初始为 0 的文件位置 k 。 此文件位置为从文件开始字节移动的量 。 程序可通过 s 运行 。eek, 显示当前文件的位置 。
    (4) 读写文件 : 复制读写文件 n020 字节到内存, 从当前文件位置 k 开始, 添加文件到 k+n 。 k> = m 时装入 EOF 。类似的写工是从存储器复制n00字节为句子文件, 从当前文件位置 k 开始更新 k 。
    (5) 关闭文件, 当内核释放门文件打开时创建的数据结构 。 此描述将被恢复到可用的描述库 。

Unix I/O 函数 :
( 1)int open ( char* filename, int flags, mode_t mode). 进程使用 open 函数来打开已有的文件或创建新文件 。 open 函数将 filename 转换为文件描述符并返回描述 。符咒数字, 返回说明符总是进程未打开的最小说明符 。 flags 参数提示了进程如何访问此文件 。 mode 参数指定访问新文件的权限 。
(2) int close( fd) 、 fd 是需要关闭的文件的描述符 。 close 返回结果 。
( 3 ) ssize_t read (intfd, void * buf, size_tn). read 函数允许您从当前文件位置的最大 n 字节到内存位置 buf 的值 。返回值 - 1 为错误, 0 为 EOF, 否则返回值将显示真实值 。传输字节数量。
(4) ssize_t wirte (int fd, const void * buf, size_tn) , write函数将从内存位置 buf 复制到多个 n 字节, 说明者为 fd 的当前文件位置。
8.3 printf的实现分析
分析首先查看printf函数的函数体:

  1. static int printf(const char *fmt, …)
  2. {
  3.  va_list args;
    
  4.  int i;
    
  5.  va_start(args, fmt);
    
  6.  write(1,printbuf,i=vsprintf(printbuf, fmt, args));
    
  7.  va_end(args);
    
  8.  return i;
    

9.}

printf程序按照格式fmt结合参数args生成格式化之后的字符串,并返回字串的长度。

接下来是write函数:
1.write:
2. mov eax, _NR_write
3. mov ebx, [esp + 4]
4. mov ecx, [esp + 8]
5. int INT_VECTOR_SYS_CALL

由 printf 调用系统函数 write (buf, i) , write 函数将堆栈参数放入寄存器 。 ecx是字符数量。 ebx 保存第一个字符地址 。
使用intINT_VECTOR_SYS_CALLA代表系统呼叫 syscall 。
查看syscall函数体:
1.sys_call:
2.call save
3.
4. push dword [p_proc_ready]
5.
6. sti
7.
8. push ecx
9. push ebx
10. call [sys_call_table + eax * 4]
11. add esp, 4 * 3
12.
13. mov [esi + EAXREG - P_STACKBASE], eax
14. cli
15. ret
8.4 getchar的实现分析
getchar 的源代码为:

  1. int getchar(void)
  2. {
  3. static char buf[BUFSIZ];
  4. static char *bb = buf;
  5. static int n = 0;
  6. if(n == 0)
  7. {
  8. n = read(0, buf, BUFSIZ);
  9. bb = buf;
  10. }
  11. return(–n >= 0)?(unsigned char) *bb++ : EOF;
  12. }
    8.5本章小结
    本章主要介绍了 Linux 的 IO 设备管理方法、Unix IO 接口及其函数,分析了 printf 函数和 getchar 函数的实现。

结论
用计算机系统的语言,逐条总结hello所经历的过程。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
附件
列出所有的中间产物的文件名,并予以说明起作用。

Hello.i 预处理后文本文件
Hello.s 编译后的文本文件
Hello.o 可重定位目标文件
Hello 链接后的目标文件
Hello.out

参考文献
为完成本次大作业你翻阅的书籍与网站等
[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.

哈工大 2021春 计算机系统 大作业 L190201101-朴仁洪相关推荐

  1. 哈工大 2021春 计算机系统 大作业程序人生

    计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机 学 号 1190200828 班 级 1936601 学 生 赵英帅 指 导 教 师 刘宏伟 计算机科学与技术学院 202 ...

  2. 哈工大2021春计算机系统大作业 程序人生-Hello’s P2P

          计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算机类 学     号 1190200613 班     级 1903004 学       生 ...

  3. 哈工大2022春计算机系统大作业

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算机类 学   号 班   级 学       生 指 导 教 师 计算机科学与技术学院 2021年5月 摘 ...

  4. 2021春计算机系统大作业

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算学部 学    号 1190201420 班    级 1903004 学       生 马立凡 指 导 ...

  5. 哈工大2022春计算机系统大作业:程序人生-Hello‘s P2P

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算机类 学   号 120L021305 班   级 2003002 学       生 李一凡 指 导 教 ...

  6. 哈工大2022秋计算机系统大作业-程序人生(Hello‘s P2P)

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算机科学与技术 学    号 班    级 学       生 指 导 教 师 刘宏伟 计算机科学与技术学院 ...

  7. 2022春 计算机系统大作业 程序人生-Hello’s P2P

    计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 班 级 学 生 指 导 教 师 计算机科学与技术学院 2022年5月 摘 要 为深入理解计算机系统,本文以hel ...

  8. 哈工大2022春CSAPP大作业-程序人生(Hello‘s P2P)

    摘  要 本论文研究了hello.c这一简单c语言文件在Linux系统下的整个生命周期,以其原始程序开始,依次深入研究了编译.链接.加载.运行.终止.回收的过程,从而了解hello.c文件的" ...

  9. 哈工大2022秋计算机系统大作业——程序人生

    目录 第1章 概述 1.1 Hello简介 1.2 环境与工具 1.3 中间结果 1.4 本章小结 第2章 预处理 2.1 预处理的概念与作用 2.2在Ubuntu下预处理的命令 2.3 Hello的 ...

最新文章

  1. potainer 日志_实时Web日志分析神器
  2. 【c语言】输入两个数,交换这两个数后,再输出
  3. 数据结构(3) -- 栈和队列
  4. 如何解决VMware Workstation 10.0.0 build-1295980马赛克现象
  5. 今天听说了一个压缩解压整型的方式-group-varint
  6. Swift项目中不能定义OC类继承Swift类
  7. php中foreach()的用法
  8. 人工智能的发展_人工智能发展带来的机遇
  9. jflash添加芯片_【原创】巧用J-Link+J-Flash给Kinesis烧写序列号
  10. leaflet地图原理_Web地图呈现原理
  11. java print快捷键_请问eclipse中输出的快捷键是什么?
  12. 【国庆特辑】43份元宇宙报告
  13. linux 系统级性能分析工具 perf 的介绍与使用
  14. 搭建Android上的服务器
  15. C Primer Plus编程题-第五章 运算符、表达式和语句
  16. 高效算法——05列文斯登距离(Python)
  17. 【小程序】如何开发属于自己的一款小程序
  18. 【元胞自动机】基于元胞自动机模拟商场人流量matlab代码
  19. python for多线程_python for 怎么多线程
  20. 01.软件项目管理与敏捷方法——敏捷项目生命周期详解笔记

热门文章

  1. 计算机基础及msoffice应用一级教程,全国计算机等级考试一级教程——计算机基础及MS Office应用(2013年版)...
  2. Au3对excel保护状态下特定列或行解锁操作
  3. Dotween SetEase Ease缓动函数
  4. 中小银行的云计算后台
  5. [论文笔记]Decoupling Direction and Norm for Efficient Gradient-Based L2 Adversarial Attacks and Defenses
  6. Decoupling Representation and Classifier for Long-Tailed Recognition
  7. TestPatten测试
  8. VMwarePlayer配置Linux
  9. oracle discoverer 10g手册 下载,Oracle Discoverer10g手册(创建维护和管理
  10. 自定义流式布局View