【计算机系统-hello的一生】

本文详细研究了Hello,world程序从源代码到执行的全过程,涵盖预处理、编译、汇编、链接以及进程管理和存储管理。通过实验验证,分析了程序如何转化为进程,探讨了Linux环境下的内存管理,包括虚拟地址到物理地址的转换、异常与信号处理。文章强调了理解计算机系统对优化编程的重要性。
摘要由CSDN通过智能技术生成

计算机系统

大作业

题     目  程序人生-Hello’s P2P 

专       业     信息安全专业                  

学     号      2021112962                 

班     级      2103201                 

学       生      欧智滔               

指 导 教 师       刘宏伟                

计算机科学与技术学院

2022年5月

摘  要

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

关键词:计算机系统;hello的一生;系统                           

(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分

    你可知“Hello,world!”的一生?从高级语言到进程打印输出,操作系统和软硬件环环相扣,共同托起“Hello,world!”的一世。本文将仔细研究程序到进程的各个环节,主要包括预处理、编译、汇编、链接、进程管理、异常与信号处理、存储管理等,采用实验验证的方式,一边实验一边验证。借此机会凝聚计算机系统的知识点,期望读者在日常的编程中能以计算机系统这一大体系的角度去思考问题,并以优化、简练的方式处理问题。

目  录

第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.c的C语言文件,往里面写入程序,之后对其分别进行预处理、编译、汇编、链接,之后生成了可执行文件hello

之后打开我们的终端(在linux环境下),输入./hello 2021112962 欧智滔 1,此时我们的终端shell,会fork一个新进程(fork是一个创建子进程的函数),接着使用execve函数(系统函数)将hello的上下文加载入这个子进程,至此CPU将开始执行hello程序。

而hello程序执行结束之后,将会发送异常处理信号给内核,内核再将上下文交还给别的进程,而且在这之前shell程序都会等待fork出来的hello程序这个子进程结束,回收其资源。

在整个过程中,linux采用的是页表存储,shell在fork一个新进程的时候并不会将整个文件导入到内存中,而是作一个地址标记处理(也就是记住它在磁盘的地址),当真正执行程序的时候,对于需求的块/节,才会进行一个调用,比如说执行指令需要代码块,则会调度代码块所在页放入主存中,当然也可能直接放入TLB表中,TLB表就是页表的一个缓存表。

1.2 环境与工具

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

系统环境:本机:windows10,虚拟机ubuntu22.04

软件环境:VMware,Vscode

硬件环境:Intel平台,虚拟机AMD平台,内存分别是32G和8G,存储空间管够

开发和调试工具:gcc、g++、gdb、readelf、edb、vim

1.3 中间结果

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

hello.c:源文件

hello.i:与处理过后的源文件

hello.s:编译预处理后的文件生成的文件

hello.o:汇编hello.s生成的可重定向文件

hello:可执行文件

hello.elf:hello.o的elf格式,可以用来展示重定向

hello.asm:hello的反汇编,可以分析其汇编语言

1.4 本章小结

       本章以走马观花的形式走过了hello的一生,program to process(p2p)、zero to zero(020)囊括了hello的一生,从一个程序到一个进程,从什么都没有再到被回收了什么都没有,其中各个环节,都是计算机人的精华结晶,里面是前人的智慧,是程序员的心血。

(第1章0.5分)

第2章 预处理

2.1 预处理的概念与作用

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

概念:

预处理是由预处理器(preprocessor)对程序源代码文本进行处理,得到的结果再由编译器进一步编译。

其中一般处理头文件、宏、条件编译、标识等

头文件是指将#include包含的文件插入到指定位置

宏指的是将所有宏定义进行替换,比如#define等

条件编译是指处理#if、#ifdef、#else等条件编译,处理方式近似宏

标识是指添加行号等符号并删掉注释等,方便编译调试

作用:

宏定义可以方便我们编程,在编程的时候方便我们进行统一修改。

头文件将一系列函数封装成一个库,方便我们调用,是一种模块化、组件化。

添加行号方便我们在编译调试的时候快速锁定想要调试的地方。

2.2在Ubuntu下预处理的命令

(图2.1)Ubuntu下预处理的命令

其中m64是按64位进行预处理,-no-pie是关闭pie保护,pie保护会随机程序起始地址,起到一个保护作用。

-fno-PIC表明使用静态链接。

-E是表明使用预处理。

2.3 Hello的预处理结果解析

可以发现头文件展开之后有大量引用。如图2.2所示。

图(2.2)头文件展开后的引用

      

       可以在下面看到很多数据别名定义。如图(2.3)所示

图(2.3)数据变量别名

预处理后的程序多达1000多行,如图(2.4)所示

图(2.4)预处理后的源程序

2.4 本章小结

本章介绍了预处理的一些基本处理过程,其中重点的是头文件的展开,以及宏定义的转换,头文件的展开使得原本小小的程序变成了较为大的文件,有助于接下来的处理,下节将会提及。

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

(第2章0.5分)

第3章 编译

3.1 编译的概念与作用

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

注意:这儿的编译是指从 .i 到 .s 即预处理后的文件到生成汇编语言程序

概念:编译的目的是将目标代码转变为汇编代码,汇编语言更接近底层,能够直观地看到CPU的寄存器、内存调用等信息。

整个过程包括:词法分析、语法分析、语义分析、源代码优化、生成代码并优化

词法分析是指将源代码的字符序列分割成一系列记号

语法分析将分割而来的一系列记号生成一个语法树

语义分析则判断所编写的源代码是否合法

源代码优化即编译器对源代码进行一个优化,常见的优化选项有O1、O2、O3

最后由编译器生成代码并对汇编进一步进行优化

3.2 在Ubuntu下编译的命令

图(3.2)在Ubuntu下编译的命令

3.3 Hello的编译结果解析

3.3.1寄存器传参

通过观察hello.s不难发现编译后的结果中的数据,大部分是由寄存器进行传参的。

图(3.3.1)在寄存器传参

3.3.2局部变量存栈区

注意rbp为栈帧寄存器,指明栈帧的位置,通过相对寻址找到局部变量存放的位置。

图(3.3.2)局部变量放栈区

3.3.3字符串常量

字符串一般存在.text节,可以看到所使用的两个字符串都在.text节中存储,且都有标号

图(3.3.3)字符串常量

3.3.4比较语句

比较语句通过cmp汇编指令来实现,通过cmp结果来设置标志,达到一定条件则跳转等。

图(3.3.4)比较语句

3.3.5分支语句

跟C语言里的if、else语句相对应,分支语句用于跳转,通常是j开头的汇编语言。

图(3.3.5)分支语句

3.3.6循环语句

循环语句是通过比较、分支语句实现的,如下图所示

图(3.3.6)循环语句

3.3.7数组操作

数组是首地址加偏移得到的,可以在汇编代码中看到程序以这种形式取了字符串的值

图(3.3.7)数组操作

3.3.8函数调用

函数调用前的参数在64位程序中采用寄存器+栈传参的方式,所用的寄存器是rdi、rsi、rdx、rcx、r8、r9。多的参数放在栈里进行传参。

图(3.3.8)函数调用

3.3.10函数返回

函数返回需要恢复栈帧以及寄存器等,具体操作为leave,而leave=mov esp, ebp和pop ebp。

图(3.3.10)函数返回

3.4 本章小结

本章的核心是汇编语言,具体包括数据操作、运算、分支控制、调用与返回等,需要明白各个环节汇编语言的作用。接下来对于汇编语言文件,将会进行汇编成机器语言,汇编语言虽接近底层,但是仍能给程序员提供阅读,而机器语言则难以阅读了。

(第32分)

第4章 汇编

4.1 汇编的概念与作用

       概念:这里的汇编是指汇编器将hello.s文件内的汇编指令转换为机器指令,供机器执行。

       作用:将汇编语言翻译成可重定位的二进制目标文件。 

4.2 在Ubuntu下汇编的命令

图(4.1)在Ubuntu下汇编的指令

4.3 可重定位目标elf格式

4.3.1 ELF头

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

图(4.3)ELF头

ELF头以一个16字节的序列开始,这个序列描述生成了该文件的系统的字的大小和字节顺序。ELF头剩下的部分包含帮助链接器语法分析和解释目标文件的信息。其中包括ELF头的大小、目标文件的类型(如可重定位、可执行或者共享的)、机器类型(如x86-64)、节头部表(section

header

table)的文件偏移,以及节头部表中条目的大小和数量。不同节的位置和大小是由节头部表描述的,其中目标文件中每个节都有一个固定的大小的条目。

具体代码格式如下:

#define EI_NIDENT 16

typedef struct{

unsigned char e_ident[EI_NIDENT];

//包含用以表示ELF文件的字符,以及其他一些与机器无关的信息。开头的4个字节值固定不变,为0x7f和ELF三个字符。

Elf32_Half e_type;// 标识的是该文件的类型

Elf32_Half e_machine;// 表明运行该程序需要的体系结构

Elf32_Word e_version;// 表示文件的版本

Elf32_Addr e_entry;// 程序的入口地址

Elf32_Off e_phoff;// 表示Program header table 在文件中的偏移量

Elf32_Off e_shoff;// 表示Section header table 在文件中的偏移量

Elf32_Word e_flags;// 对IA32而言,此项为0

Elf32_Half e_ehsize;// 表示ELF header大小

Elf32_Half e_phentsize;// 表示Program header table中每一个条目的大小

Elf32_Half e_phnum;// 表示Program header table中有多少个条目

Elf32_Half e_shentsize;// 表示Section header table中的每一个条目的大小

Elf32_Half e_shnum;// 表示Section header table中有多少个条目

Elf32_Half e_shstrndx;// 包含节名称的字符串是第几个节

} Elf32_Ehdr;

4.3.2 ELF节表头目

节表头目通常包含一下几个节:

.text

.rodata

.data

.bss

.symtab

.rel.text

.rel.data

.debug

.line

.strtab

其中.text节保存了已编译程序的机器代码

.rodata节保存了只读数据

.data节保存了已初始化的全局和静态变量

.bss节保存了未初始化的全局和静态变量

.symtab节保存了引用的函数以及全局变量的信息,是一个符号表

.rel.text节用于重定向.text里面的内容

.rel.data节用于重定向.data里面的内容

.debug节用于调试
.line节保存了源程序的行号和.text节的机器代码之间的映射关系

.strtab节是字符串表

图(4.3.2)节点头表

4.4 Hello.o的结果解析

这里我们使用objdump来分析hello.o

图(4.4.1)hello.o的反汇编形式(1)

图(4.4.2)hello.o的反汇编形式(2)

相比于hello.s

对比main函数,两者的代码大差不差,机器指令对于指定汇编语言。

在跳转语句上:.s文件使用的L3/L4跳转标识改变成了具体地址。

函数的调用上:同上,将符号改成了具体地址。

全局变量访问上:.s文件中访问时用段名加%rip,反汇编时用0+%rip。

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

4.5 本章小结

本章以汇编的角度分析了可重定向文件的ELF头和节点头表等等,整个过程将汇编转变为机器指令,方便于机器执行代码,并且生成了可重定向信息,为接下来的重定向做好了准备。

(第41分)

5章 链接

5.1 链接的概念与作用

链接的概念:链接是指将处于不同模块的文件连接在一起,进行参数的传递以及控制的传递,将不同模块整合成一个整体。

链接的作用:使得程序高度模块化、集成化,有助于代码的高效开发。

5.2 在Ubuntu下链接的命令

图(5.2)在Ubuntu下链接的命令

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

ELF头:

这里描述了ELF文件的基本信息

图(5.3.1)ELF头信息

节头:

这里描述了各个节的大小、偏移等属性,小段之间会结合成一个大段。

图(5.3.2)节头信息(上)

图(5.3.3)节头信息(下)

5.4 hello的虚拟地址空间

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

用edb加载hello文件

图(5.4.1)hello的虚拟地址空间

可以观察到程序的起始地址等信息,这里的地址是虚拟地址,程序在执行的时候需要将虚拟地址映射到物理地址才能真正执行。

程序的进程虚拟地址空间细则如下:

图(5.4.2)程序的虚地址空间

5.5 链接的重定位过程分析

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

程序dump之后:

图(5.5.1)objdump程序的重定向分析

区别:

Hello中增添了.init节以及.plt节,还在链接中直接加入了所用到的库函数,比如write、read、exit等

函数调用方面地址全都为虚拟内存地址,无重定向条目,而对于hello.o的反汇编代码,在.rel.data/.rel.text节中有重定向条目,因为只有链接的时候才会将其重定向到运行时的虚拟地址。

同时一些数据,比如数组等的地址,也被替换成了虚拟地址,被重定向了。

5.6 hello的执行流程

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

图(5.6.1)edb执行hello程序

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

dl_start        0x7fce8cc38ea0

dl_init         0x7fce8cc47630

start             0x400500

libc_start_main        0x7fce8c867ab0

cxa_atexit          0x7fce8c889430

libc_csu_init     0x4005c0

init                     0x400488

_setjmp                    0x7fce8c884c10

_sigsetjmp                0x7fce8c884b70

__sigjmp_save         0x7fce8c884bd0

main 0x400532

puts@plt

exit@plt

printf@plt

sleep@plt

getchar@plt

dl_runtime_resolve_xsave     0x7fce8cc4e680

dl_fixup                                 0x7fce8cc46df0

dl_lookup_symbol_x             0x7fce8cc420b0

exit                                         0x7fce8c889128

开始的dl_init是库初始化的函数,然后进入主程序的start函数,之后调用库的libc_start_main函数,在下面的@plt函数关系到linux的一个动态链接执行流程,linux下程序有两个表,一个plt表,一个got表,都是用来定位在库里面函数的位置的,当执行这个函数的时候,先回会去访问plt表的地址,之后plt表会访问got表对应函数地址,这个时候程序寻找最终地址,并记录在got表里,此时got表拥有函数真实的地址,plt表指向got表。

5.7 Hello的动态链接分析

动态链接的时候,库将会放在物理内存的一段位置,与程序独立开来。

具体访问过程就如上文讲述的got表和plt表的变换。

通过反汇编可以找到plt、got表的虚拟地址位置

图(5.7.1)plt表和got表的虚拟地址

执行前的plt表:

图(5.7.2)执行前的plt表

执行前的got表:

图(5.7.3)执行前的got表

图(5.7.4)执行后的plt表

图(5.7.5)执行后的got表

这里执行前后plt表内容一致,是因为他们都指向got表,而got表在执行dl_init之后被更改。

5.8 本章小结

本章主要学习了程序连接的过程,分为静态连接和动态连接,其中动态链接主要理解了动态链接前后plt表和got表的变化,以及与其节点的关系,实际上,连接远比这复杂,它是程序员的精华结晶之一。

(第51分)

6章 hello进程管理

6.1 进程的概念与作用

进程的概念:进程是指执行中的程序以及其数据/结构等信息的一个集合,由操作系统分配统一的pid号。

进程的作用:进程将不同程序划分为不同的区块,避免了拥挤地占满内存,方便系统统一管理。

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

Shell-bash作用:解释命令,并执行相对应的操作,连接用户与操作系统。

首先shell-bash会解析命令,按照某个约定(特殊字符&^!空格等)划分为几个小块,这些小块都会复制一份到argv数组,如果发现是内置的命令,则会执行此命令,否则将会调用程序执行,fork出一个新进程,将argv传入,env传入,filename传入,之后等待返回。

6.3 Hello的fork进程创建过程

在6.2所说的argv数组,实际上shell在解析命令之后,会创建argc、argv、filename、envp等参数列表,当fork出子进程的时候,子进程与父进程具有相同的虚拟地址,采用写时复制的策略,虚拟地址独立,PID不同,但是gpid一致。

6.4 Hello的execve过程

创建子进程之后,调用execve函数,并且参数为filename,argv,envp,让子进程在上下文加载运行程序,并且创建新的代码段,PC指向程序入口地址,开始执行程序。

6.5 Hello的进程执行

上下文:上下文通常包括通用目的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈、和各种内核数据结构等。

如图进程调度过程演示所示:

图(6.5.1)进程调度演示

调度的过程:

在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占了的进程,这种决策就叫做调度,是由内核中称为调度器的代码处理的。当内核选择一个新的进程运行,我们说内核调度了这个进程。在内核调度了一个新的进程运行了之后,它就抢占了当前进程,并使用上下文切换机制来将控制转移到新的进程。

以执行sleep函数为例,sleep函数请求调用休眠进程,sleep将内核抢占,进入倒计时,当倒计时结束后,hello程序重新抢占内核,继续执行。

用户态与核心态转换:

为了能让处理器安全运行,不至于损坏操作系统,必然需要先知应用程序可执行指令所能访问的地址空间范围。因此,就存在了用户态与核心态的划分,核心态可以说是“创世模式”,拥有最高的访问权限,处理器以一个寄存器当做模式位来描述当前进程的特权。进程只有故障、中断或陷入系统调用时才会得到内核访问权限,其他情况下始终处于用户权限之中,保证了系统的安全性。

Hello在调用sleep时若发生被占的情况,则上下文会发生切换,进入内核状态,内核处理休眠之后主动释放当前进程,定时器发送一个中断信号,由中断处理函数完成处理,将 Hello 进程从等待 队列中移出重新加入到运行队列,从而进行上下文切换进入到 Hello 进程。

6.6 hello的异常与信号处理

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

程序正常运行时:

图(6.6.1)程序正常运行

Hello执行过程共有可能出现下面的异常类型分别为:

中断、陷阱、故障、终止。

其原因分别为:

来自I/O设备的信号、有意的异常、潜在可恢复的错误、不可恢复的错误。

处理方式分别为:

图(6.6.2)中断处理方式

图(6.6.3)陷阱处理方式

图(6.6.4)故障处理方式

图(6.6.5)终止处理方式

按下Ctrl+Z,进程会收到停止信号,hello进程将会被挂起。

图(6.6.6)Ctrl+Z进程挂起

按下Ctrl+C,进程会接收到终止信号,hello进程将会结束。

图(6.6.7)Ctrl+C进程结束

中途乱按,输入只会进入到缓冲区里,对程序本地并无大影响。

图(6.6.8)中途乱按

ps命令:观察现有进程

图(6.6.9)ps命令

Jobs命令:查看当前命令内容

图(6.6.9)jobs命令

Pstree命令:用进程树把各个进程用树状图的方式链接起来。

图(6.6.10)pstree命令

Fg命令:让挂起的进程继续执行。


      

图(6.6.11)fg命令

Kill指令:杀掉指定进程。

图(6.6.12)kill命令

6.7本章小结

本章深入了解了hello进程的从创建到回收的整个过程,从shell-bash命令解析,到fork出新线程,再到execve调用文件,最后还有异常处理,以及上下文切换等,他们是现代计算机的核心,通过这一章的学习,我们对操作系统运行程序有了一个更加鲜明、细微的认识。

(第61分)

7章 hello的存储管理

7.1 hello的存储器地址空间

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

逻辑地址:

逻辑地址是指程序产生的与段相关的偏移地址。

线性地址:

线性地址是逻辑地址到物理地址之间的一个中间层,段加偏移生成线性地址。

虚拟地址:

虚拟地址就是程序运行时表面上执行的地址,虚拟地址有助于进程之间相互独立。

物理地址:

物理地址是指程序运行/数据所保存在的真是物理地址。

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

在段式存储管理中,将程序的地址空间划分为若干个段(segment),这样每个进程有一个二维的地址空间。在前面所介绍的动态分区分配方式中,系统为整个进程分配一个连续的内存空间。而在段式存储管理系统中,则为每个段分配一个连续的分区,而进程中的各个段可以不连续地存放在内存的不同分区中。

程序加载时,操作系统为所有段分配其所需内存,这些段不必连续,物理内存的管理采用动态分区的管理方法。在为某个段分配物理内存时,可以采用首先适配法、下次适配法、最佳适配法等方法。在回收某个段所占用的空间时,要注意将收回的空间与其相邻的空间合并。段式存储管理也需要硬件支持,实现逻辑地址到物理地址的映射。

程序通过分段划分为多个模块,如代码段、数据段、共享段:可以分别编写和编译;可以针对不同类型的段采取不同的保护;可以按段为单位来进行共享,包括通过动态链接进行代码共享。这样做的优点是:可以分别编写和编译源程序的一个文件,并且可以针对不同类型的段采取不同的保护,也可以按段为单位来进行共享。

总的来说,段式存储管理的优点是:没有内碎片,外碎片可以通过内存紧缩来消除;便于实现内存共享。缺点与页式存储管理的缺点相同,进程必须全部装入内存。

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

页式管理将各进程的虚拟空间划分成若干个长度相等的页(page),然后把页式虚拟地址与内存地址建立一一对应页表,并使用MMU来进行地址的转换,在查询页表的时候还加上了页表的缓存,TLB表,用来解决高校寻址问题。

优点:节约大量内存,无用的页表存在磁盘中,实现了分块管理,有效地解决了碎片问题。

还提供了硬件统一管理的方式,内存外存统一管理,使用户可以使用的存储空间大大提升,提高了主存的利用率。

缺点:对硬件的要求更高了,需要硬件具有相对应的处理能力。

还增加了系统的开销,当发生缺页的时候占用系统资源。

如果频繁地发生页的调度与替换,将会大大影响电脑的性能。

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

图(7.4)VA到PA的转换

图(7.4.2)四级页表下,VA到PA的转换

如上述两图所示,VA到PA的转换需要MMU的参与,MMU会解析VA,然后进一步在TLB/PTEA里面查找PPN,在多级页表下,VPN会被划分为VPN1、VPN2等多级页表的VPN,具体流程如上图所示。

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

三级Cache下CPU对访问数据,首先会查询L1,如果L1未命中,将会查询L2,之后将会查询L3,最后如果还是未命中将会查询主存,最后才是磁盘,其查询时间越增越大,查询的代价越来越大。

7.6 hello进程fork时的内存映射

Fork函数调用的时候,内核会为子进程创建各种数据结构,并分配pid。

创建当前进程的mm_struct、区域结构和页表的原样副本。它将两个进程中的每个页面都标记位只读,并将两个进程中的每个区域结构都标记为私有的写时复制。

当改变数据的时候采用写时复制,创建新页面,保证私有地址的私有性。

7.7 hello进程execve时的内存映射

Execve操作的时候执行下面几个步骤:

创建了当前进程的mm_struct、区域结构和页表的原样副本。它将两个进程中的每个页面都标记位只读,并将两个进程中的每个区域结构都标记为私有的写时复制。

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

映射共享区域。如果hello程序域共享对象链接,这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。

设置程序计数器(PC)。execve做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向代码区域的入口点。

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

图(7.8.1)缺页异常处理

如上图所示,缺页的时候将会执行替换策略,并找寻到对应的页放入对应的位置之中。

7.9本章小结

本章内存的三个管理,从分页式管理、段式管理、再到Cache的三级缓存策略,其中思想十分精妙,各个环节刚刚好,不得不让人感慨前辈的聪慧。

还介绍了hello程序的fork过程和execve过程,缺页故障处理过程、信号交互等,通过虚拟内存使得进程之间互不干扰,并且内存利用率更高。

(第7 2分)

结论

用计算机系统的语言,逐条总结hello所经历的过程。

你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。

Hello程序从程序员敲下的一个个字符开始,诞生出了hello.c。(hello.c)

经过预处理器的教养,体内变得严谨、详细。(hello.c->hello.i)

紧接着它去编译器里上学了,变得更加成熟稳重,学会了更多优化自己的技能。(hello.i->hello.s)

后来它真正长大了,一个人去了汇编器,在那里收到了知识的熏陶,思想变得深邃,不容易懂了。(hello.s->hello.o)

再后来,它遇到了链接器,在那里它组建了自己的家,有了自己的事业,成长为了大家期望的人。(hello.o->hello)

在要干活的时候,它会娴熟地使用自己的技能,召唤出一个一模一样的自己,并让同伴将工作岗位让给它的分身。(fork、execve)

最终工作结束之后它会回收自己的分身,并上交给领导所有信息。(回收)

       CSAPP蕴含着计算机的核心思想,以程序员的视角,全面地介绍了计算机系统,深入浅出地介绍了一个程序从program到process,从zero到zero的过程,详细而全面,让我深感要成为一名优秀的计算机工作者,除了外修技能之外,还需内修理论核心,要有远见,要有智慧。

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

附件

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

预处理后的文件 hello.i

编译之后的汇编文件 hello.s

汇编之后的可重定位目标文件 hello.o

链接之后的可执行目标文件 Hello

Hello.o 的 ELF 格式 hello.elf

Hello.o 的反汇编代码 hello.asm

hello的ELF 格式 hello1.elf

hello 的反汇编代码 hello1_objdump.s

(附件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.

[7]  CSDN博客 ELF可重定位目标文件格式

[8]  《步步惊芯——软核处理器内部设计分析》 TLB的作用及工作过程

[9]  CSDN博客 ELF可重定位目标文件格式

[10]  博客园 printf函数实现的深入剖析

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值