程序人生大作业

计算机系统

大作业

题     目  程序人生-Hello’s P2P 

专       业   计算学部              

学     号   1190201105            

班     级   1903006               

学       生    权悦莹               

指 导 教 师    史先俊                 

计算机科学与技术学院

2021年5月

摘  要

本文主要讲述了hello.c程序在编写完成后运行在linux中的生命历程,记住相关工具分析预处理、编译、汇编、链接等各个过程在linux下实现的原理,分析了这些过程中产生的文件的相应信息和作用。并介绍了shell的内存管理、IO管理、进程管理等相关知识,了解了虚拟内存、异常信号等相关内容。                   

关键词:预处理;编译;汇编;链接;shell;IO管理;进程管理;虚拟内存;异常信号

(摘要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(From Program to Process):用高级程序语言编写的源程序hello.c文件,分别经过预处理器cpp预处理得到hello.i文件,编译器ccl编译得到hello.s汇编语言文件,汇编器as汇编得到可重定位的helllo.o目标文件,链接器ld与库函数链接得到可执行目标文件hello。

                     图1.1:编译系统

执行此文件hello,在shell中键入命令(./hello),操作系统fork产生子进程,Hello从program成为Process,再调用execve函数加载进程。

020(From Zero-0 to Zero-0):操作系统调用execve后映射虚拟内存,先删除当前虚拟地址的数据结构并为hello创建新的区域结构,进入程序入口后载入物理内存,再进入主函数开始执行代码。程序结束后,父进程回收子进程hello,内核删除相关数据结构和状态信息。

1.2 环境与工具

1.硬件环境

Inter(R) Core(TM) i5-7200U CPU @ 2.50Ghz 2.71

2.软件环境

Windows10 64位;Vmware 15.5;Ubuntu 19.0 64位

3.开发工具

Visual Studio 2019 64位;CodeBlocks 64位;vi/vim/gedit+gcc;

Objdump;Gdb;Hexedit

1.3 中间结果

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

hello.i预处理的文本

hello.s编译的汇编文本

hello.o可重定位目标文件

hello_elf.txt: hello.o经过readelf的ELF格式

hello_dis.txt: hello.o经过objdump反汇编的

hello链接后的可执行目标文件

Hello1.s hello使用objdump反汇编后的汇编文本

Hello1_elf.txt: hello经过readelf的ELF格式

Hello1_dis.txt: hello经过objdump反汇编的

1.4 本章小结

本章主要介绍了hello的P2P,020过程,以及进行实验时的软硬件环境及开发工具和在本论文中生成的中间结果文件.

(第1章0.5分)

第2章 预处理

2.1 预处理的概念与作用

预处理器(cpp) 一般是指在程序源代码被翻译为目标代码的过程中,生成二进制代码之前的过程。根据以字符#开头的命令,修改原始的C程序。比如 hello.c中第1行的#include 命令告诉预处理器读取系统头文件 stdio.h的内容,并把它直接插人程序文本中。结果就得到了另一个C程序,通常是以.i作为文件扩展名。

2.2在Ubuntu下预处理的命令

gcc -E hello.c -o hello.i

                                            图2.2:hello.i

2.3 Hello的预处理结果解析

预处理只有#开头的部分发生了变化,得到.i文件打开后发现得到了扩展,到了3000多行,原文件中的宏进行了宏展开。

图 2.3.1:源代码的文件信息

                     图 2.3.2:源代码的文件信息

              图 2.3.3:类型的定义

                     图 2.3.4:函数声明

                            图 2.3.5:源代码

2.4 本章小结

      描述了预处理的过程及概念,和ubuntu下预处理命令,分析了预处理后的hello.i文件。

(第2章0.5分)

第3章 编译

3.1 编译的概念与作用

    编译就是把通过用高级语言编写的源程序通过编译器转变为目标程序,编译器(ccl)将文本文件hello.i翻译咸文本文件hello.s,它包含一个汇编语言程序。该程序包含函数main的定义。作用是,让每条语旬都以一种文本格式来描述一条低级机器语言指令,不同高级语言的不同编译器提供了通用的输出语言。

3.2 在Ubuntu下编译的命令:

gcc -S -c hello.c

                                                图3.2:hello.s

3.3 Hello的编译结果解析

1.全局变量:全局变量在data节中定义它,并且解释了它。

2.局部变量:局部变量会在栈中储存它,给他分配一个大小符合的字节大小。

3.控制符及其跳转:利用jump,set,cmp等指令对程序进行跳转。例如:通过比较cmpl与跳转je,jle来实现argc!=3和i<10的比较,然后转移。

5.处理结构体,数组:数组:取数组头指针加上第i位偏移量来处理;指针与数组类似,如果rax表示指针所存的寄存器,访问x指向的值就是(%rax);结构体:通过结构体内部的偏移量来访问。

6.处理函数:

(1)函数的调用与传参:给函数传参需要先设定寄存器,将参数传给所设寄存器,如果参数的数目多于6个,则其他的则采用栈的方式传递。在通过call来跳转到调用的函数开头地址。在源代码hello.c中调用了printf、getchar、sleep和exit(1):第一个printf转换成了puts,把.LC0段的立即值传入的%edi中,然后call跳转到puts。这里的exit是把立即数1传入了%edi中,然后call跳转到exit。第二个printf有三个参数,第一个是.LC1中的格式化字符串存在%eax中,后面的两个依次是%rdx和%rsi,然后call跳转到printf。接下来是sleep,它有一个参数传到%edi中,之后call跳转sleep中。getchar是不需要参数的,直接call跳转即可。

(2)返回值:函数的返回值一般存在寄存器%rax中,如果有返回值,则要先把返回值存到%rax中再用ret返回。源程序中有主函数的return 0:就是先把返回值立即数0存到%eax中,然后再ret返回。

7.字符串:存在于只读代码段。

                                                图3.3

3.4 本章小结

概括了编译的概念和作用,分析了程序的数据与操作翻译成汇编语言时的方法。

(第32分)

第4章 汇编

4.1 汇编的概念与作用

汇编是指把汇编语言翻译成机器语言的过程,编器(as)将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序(relocatable object program)的格式,并将结果保存在目标文件hello.o里。作用是,把汇编语言一一对应翻译成机器可以直接执行的机器指令。

4.2 在Ubuntu下汇编的命令

       Gcc -c hello.s -o hello.o

                                  图4.2:hello.o

4.3 可重定位目标elf格式

命令:reaelf -a hello.o > hello_elf.txt生成hello_elf.txt文件。

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

                              图4.3.1:生成read_elf.txt

                              图4.3.2:elf文件

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

                                     图4.3.3:elf头

(2)节头部表:记录各节名称、类型、地址、偏移量、大小、全体大小、旗标、链接、信息、对齐。

                                     图4.3.4:节头部表

(3).rela.text,保存的是.text节中需要被修正的信息;任何调用外部函数或者引用全局变量的指令都需要被修正;调用外部函数的指令需要重定位;引用全局变量的指令需要重定位;调用局部函数的指令不需要重定位;在可执行目标文件中不存在重定位信息.

                                     图4.3.5:.rela.text

(4).symtab,一个符号表,它存放在程序中定义和引用的函数和全局变量的信息,一些程序员错误地认为必须通过-g选项来编译一个程序,才能得到符号表信息。实际上每个可重定位目标文件在.symtab中都有一张符号表(除非程序员特意用STRIP命令去掉它)。然而,和编译器中的符号表不同,.symtab符号表不包含局部变量的条目。

                                     图4.3.6:.symtab

4.4 Hello.o的结果解析

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

图4.4.1反汇编代码

图4.4.2汇编代码

对比:

(1) 分支跳转语句:hello.s中跳转到目标位置都是用.L3/.L4等等来表示的,而反汇编之后则是用具体的地址表示。

(2) 函数调用:汇编代码中函数调用时直接个函数名称,但是反汇编后需要call加具体地址。

(3)全局变量访问:反汇编之前,访问.rodata节使用.LC0(%rip),反汇编之后是0x0(%rip),这是由于.rodata的数据地址是运行时确定的,故访问是要重定位的,所以汇编成机器语言时要设置操作全0并添加重定位条目。

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

4.5 本章小结

概述了汇编的概念和作用, ELF格式。对比了汇编程序和反汇编程序的差别。

(第41分)

5章 链接

5.1 链接的概念与作用

链接是指在电子 计算机程序 的各模块之间传递参数和控制命令,并把它们组成一个可执行的整体的过程。作用:链接器在软件开发过程中扮演着一个关键的角色,因为它们使得分离编译(separate compilation)成为可能。

5.2 在Ubuntu下链接的命令

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o hello.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/libc.so /usr/lib/x86_64-linux-gnu/crtn.o -o hello

图5.2:链接命令

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

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

readelf -a hello.o > hello1_elf.txt

                                                图5.3:elf头

5.4 hello的虚拟地址空间

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

Hello的虚拟地址空间的起始为0x400000,结束与0x400ff0。

                                                图5.4:edb

5.5 链接的重定位过程分析

objdump -d -r hello 分析hello与hello.o的不同,说明链接的过程。

结合hello.o的重定位项目,分析hello中对其怎么重定位的。

与hello.o生成的反汇编文件对比发现,hello1.txt中多了许多节。hello0.txt中只有一个.text节,而且只有一个main函数,函数地址也是默认的0x000000.hello1.txt中有.init,.plt,.text三个节,而且每个节中有许多的函数。库函数的代码都已经链接到了程序中,程序各个节变的更加完整,跳转的地址也具有参考性。

hello重定位的过程:

(1)重定位节和符号定义链接器将所有类型相同的节合并在一起后,这个节就作为可执行目标文件的节。然后链接器把运行时的内存地址赋给新的聚合节,赋给输入模块定义的每个节,以及赋给输入模块定义的每个符号,当这一步完成时,程序中每条指令和全局变量都有唯一运行时的地址。

(2)重定位节中的符号引用这一步中,连接器修改代码节和数据节中对每个符号的引用,使他们指向正确的运行时地址。执行这一步,链接器依赖于可重定位目标模块中称为的重定位条目的数据结构。

(3)重定位条目当编译器遇到对最终位置未知的目标引用时,它就会生成一个重定位条目

5.6 hello的执行流程

(1) 载入:_dl_start、_dl_init

(2)开始执行:_start、_libc_start_main

(3)执行main:_main、_printf、_exit、_sleep、

_getchar、_dl_runtime_resolve_xsave、_dl_fixup、_dl_lookup_symbol_x

(4)退出:exit

程序名称 地址

ld-2.27.so!_dl_start 0x7fb85a93aea0

ld-2.27.so!_dl_init 0x7f9612138630

hello!_start 0x400582

lib-2.27.so!__libc_start_main 0x7f9611d58ab0

hello!puts@plt 0x4004f0

hello!exit@plt 0x400530

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

5.7 Hello的动态链接分析

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

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

在调用共享库函数时,编译器没有办法预测这个函数的运行时地址,因为定义它的共享模块在运行时可以加载到任意位置。正常的方法是为该引用生成一条重定位记录,然后动态链接器在程序加载的时候再解析它。GNU编译系统使用延迟绑定,将过程地址的绑定推迟到第一次调用该过程时。动态链接器使用过程链接表PLT+全局偏移量表GOT实现函数的动态链接,GOT中存放函数目标地址,PLT使用GOT中地址跳转到目标函数。

                    图5.7.1:调用之前

                    图5.7.2:调用之后

5.8 本章小结

介绍了链接的概念和作用,可执行文件的ELF格式,虚拟地址空间的分配,重定位和执行过程还有动态链接。(第51分)

6章 hello进程管理

6.1 进程的概念与作用

进程是计算机程序需要进行对数据集合进行操作所运行的一次活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。作用是,我们的程序好像是系统中当前运行的唯一程序一样,我们的程序好像是独占的使用处理器和内存,处理器好像是无间断的执行我们程序中的指令,我们程序中的代码和数据好像是系统内存中唯一的对象。

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

作用:是一种交互型的应用级程序,时Linux的外壳,提供了一个界面,用户可以通过这界面访问操作系统内核。

处理流程:

(1)从终端读入输入的命令。

(2)将输入字符串切分获得所有的参数

(3)如果是内置命令则立即执行

(4)否则调用相应的程序为其分配子进程并运行

(5)shell应该接受键盘输入信号,并对这些信号进行相应处理

6.3 Hello的fork进程创建过程

先创造出一个子进程,然后将子进程的内容都删除完,将将要执行的文件的节头表导入,等待cpu引用该文件的第一条指令。

6.4 Hello的execve过程

execve的功能是在当前进程的上下文中加载并运行一个新程序。在执行fork得到子进程后随即使用解析后的命令行参数调用execve,execve调用启动加载器来执行hello程序。加载器执行的操作是,加删除子进程现有的虚拟内存段,并创建新的代码、数据、堆和栈段。代码和数据段被初始化为hello的代码和数据。堆和栈被置空。然后加载器将PC指向hello程序的起始位置,即从下条指令开始执行hello程序。

6.5 Hello的进程执行

逻辑控制流:如果想用调试器单步执行程序,我们会看到一系列的程序计数器(PC)的值,这些值唯一地对应于包含在程序的可执行目标文件中的指令,或是包含在运行时动态链接到程序的共享对象中的指令。这个PC值的序列叫做逻辑控制流,或者简称为逻辑流。

上下文切换:如果系统调用因为等待某个事件发生而阻塞,那么内核可以让当前进程休眠,切换到另一个进程,上下文就是内核重新启动一个被抢占的进程所需要的状态,是一种比较高层次的异常控制流。。

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

用户模式和内核模式:shell使得用户可以有机会修改内核,所以需要设置一些防护措施来保护内核,如限制指令的类型和可以作用的范围。

开始Hello运行在用户模式,收到信号后进入内核模式,运行信号处理程序,之后再返回用户模式。运行过程中,cpu不断切换上下文,使运行过程被切分成时间片,与其他进程交替占用cpu,实现进程的调度。

6.6 hello的异常与信号处理

故障:缺页异常,hello进程的页表被映射到hello文件,然而实际代码拷贝至内存仍未完成,在执行到相应地址的代码时会引发缺页异常。

终止:不可恢复错误发生。

中断:接受到键盘键入的信号,如ctrl Z ,ctrl C等

                    图6.6.1:正常

                    图6.6.2:随意输入

                    图6.6.3:ctrl+C终止

                    图6.6.4:ctrl+Z

                    图6.6.5:kill

6.7本章小结

讨论了进程的概念及作用,执行过程,shell,fork,exerce函数,异常控制流。(第61分)

7章 hello的存储管理

7.1 hello的存储器地址空间

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

逻辑地址:汇编程序中地址。逻辑地址由选择符和偏移量组成。

线性地址:逻辑地址经过段机制后转化为线性地址,为描述符:偏移量的组合形式。分页机制中线性地址作为输入。

虚拟地址:类似于线性地址

物理地址:真实的物理内存对应地址。 CPU对内存的访问是通过连接着CPU和北桥芯片的前端总线来完成的。在前端总线上传输的内存地址都是物理内存地址

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

8086共设计了20位宽的地址总线,通过将段寄存器左移4位加上偏移地址得到20位地址,即逻辑地址。将内存分为不同的段,每个段有段寄存器对应,段寄存器有一个栈、一个代码、两个数据寄存器

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

系统将每个段分割为被称为虚拟页(VP)的大小固定的块来作为进行数据传输的单元,在linux下每个虚拟页大小为4KB,类似地,物理内存也被分割为物理页(PP/页帧),虚拟内存系统中MMU负责地址翻译,MMU使用存放在物理内存中的被称为页表的数据结构将虚拟页到物理页的映射,即虚拟地址到物理地址的映射。

                                          图7.3:地址翻译

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

将VPN分成三段,对于TLBT和TLBI来说,可以在TLB中找到对应的PPN,但是有可能出现缺页的情况,这时候就需要到页表中去找。此时,VPN被分成了更多段(这里是4段)CR3是对应的L1PT的物理地址,然后一步步递进往下寻址,越往下一层每个条目对应的区域越小,寻址越细致,在经过4层寻址之后找到相应的PPN让你和和VPO拼接起来

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

使用7.4环境中获得的PA,首先取组索引对应位,向L1cache中寻找对应组。如果存在,则比较标志位,并检查对应行的有效位是否为1。如果上述条件均满足则命中。否则按顺序对L2cache、L3cache、内存进行相同操作,直到出现命中。然后向上级cache返回直到L1cache。如果有空闲块则将目标块放置到空闲块中,否则将缓存中的某个块驱逐,将目标块放到被驱逐块的原位置。

7.6 hello进程fork时的内存映射

在shell输入命令行后,内核调用fork创建子进程,为hello程序的运行创建上下文,并分配一个与父进程不同的PID。通过fork创建的子进程拥有父进程相同的区域结构、页表等的一份副本,同时子进程也可以访问任何父进程已经打开的文件。当fork在新进程中返回时,新进程现在的虚拟内存刚好和调用fork时存在的虚拟内存相同,当这两个进程中的任一个后来进行写操作时,写时复制机制就会创建新页面,因此,也就为每个进程保持了私有地址空间。

7.7 hello进程execve时的内存映射

execve函数调用驻留在内核区域的启动加载器代码,在当前进程中加载并运行包含在可执行目标文件hello中的程序,用hello程序有效地替代了当前程序。加载并运行hello需要以下几个步骤:

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

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

(3)映射共享区域, hello程序与共享对象libc.so链接,libc.so是动态链接到这个程序中的,然后再映射到用户虚拟地址空间中的共享区域内。

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

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

如果程序执行过程中遇到了缺页故障,则内核调用缺页处理程序。处理程序会进行如下步骤:检查虚拟地址是否合法,如果不合法则触发一个段错误,程序终止。然后检查进程是否有读、写或执行该区域页面的权限,如果不具有则触发保护异常,程序终止。在两步检查都无误后,内核选择一个牺牲页面,如果该页面被修改过则将其交换出去,换入新的页面并更新页表。然后将控制转移给hello进程,再次执行触发缺页故障的指令。

7.9动态存储分配管理

基法与策略:通过维护虚拟内存,一种是隐式空闲链表,另一种是显式空闲链表。显式空闲链表法是malloc(size_t size)每次声明内存空间都保证至少分配size_t大小的内存,双字对齐,每次必须从空闲块中分配空间,在申请空间时将空闲的空间碎片合并,以尽量减少浪费。而隐式链表的不同之处:会每隔一段时间检查是否有已经空闲的块,将已经空闲下来的块释放,不会留下没有根的链表块

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

7.10本章小结

讲述了存储器的地址空间,虚拟地址、物理地址、线性地址、逻辑地址,进程fork和execve的内存映射,缺页异常的方法和malloc的内存分配。(第7 2分)

8章 hello的IO管理

8.1 Linux的IO设备管理方法

设备的模型化:文件

文件的类型:

1.普通文件(regular file):包含任意数据的文件。

2.目录(directory):包含一组链接的文件,每个链接都将一个文件名映射到一个文件(“文件夹”)。

3.套接字(socket):用来与另一个进程进行跨网络通信的文件

4.命名通道

5.符号链接

6.字符和块设备

设备管理:unix io接口

1.打开和关闭文件

2.读取和写入文件

3.改变当前文件的位置

8.2 简述Unix IO接口及其函数

打开和关闭文件:

1.open()函数:打开一个已经存在的文件,若干不存在则创建一个新的文件。

int open(char* filename,int flags,mode_t mode);

2.close()函数:关闭一个已经打开的文件。

int close(fd);

读取和写入文件:

1.read()函数:从当前文件位置复制字节到内存位置。

ssize_t read(int fd,void *buf,size_t n);

2.write()函数:从内存复制字节到当前文件位置。

ssize_t wirte(int fd,const void *buf,size_t n);

读写文件时,如果返回值<0则说明出现错误

改变文件位置:

lseek()函数

8.3 printf的实现分析

sprintf函数的作用是将所有的参数内容格式化之后存入buf,然后返回格式化数组的长度。write函数是将buf中的i个元素写到终端的函数。从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall.字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。

8.4 getchar的实现分析

异步异常-键盘中断的处理:当用户按键时,键盘接口会得到一个代表该按键的键盘扫描码,同时产生一个中断请求,中断请求抢占当前进程运行键盘中断子程序,键盘中断子程序先从键盘接口取得该按键的扫描码,然后将该按键扫描码转换成ASCII码,保存到系统的键盘缓冲区之中。getchar函数落实到底层调用了系统函数read,通过系统调用read读取存储在键盘缓冲区中的ASCII码直到读到回车符然后返回整个字串,getchar进行封装,大体逻辑是读取字符串的第一个字符然后返回。

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

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

8.5本章小结

Linux提供了一种简单使用的抽象——将系统的IO设备抽象成文件,系统的输入和输出被抽象成文件的写和读操作。在此基础上,Linux对系统IO的操作可以以打开文件、改变文件位置、读写文件、关闭文件的操作进行。同时分析了printf和getchar的实现

(第81分)

结论

1.预处理:将hello.c调用的所有外部的库合并到一个hello.i文件中。

2.编译,hello.i编译成为汇编文件hello.s。

3.汇编,hello.s会变成为可重定位目标文件hello.o。

4.链接,将hello.o与可重定位目标文件和动态链接库链接成为可执行目标程序hello

5.运行:shell中运行hello。

6.创建子进程:shell进程调用fork为其创建子进程。

7.运行程序:shell调用execve,execve调用启动加载器,加映射虚拟内存,进入程序入口后程序开始载入物理内存,然后进入 main函数。

8.执行指令:hello享有CPU资源,顺序执行自己的控制逻辑流.

9.访问内存:MMU将程序中使用的虚拟内存地址通过页表映射成物理地址。

10.动态申请内存:printf会调用malloc向动态内存分配器申请堆中的内存。

11.信号:如果运行途中键入中断,则调用shell的信号处理函数分别停止、挂起。

12.结束:shell父进程回收子进程,内核删除为这个进程创建的所有数据结构。如果父程序不能回收该子程序,则由中断直接收回。

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

附件

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

hello.i预处理的文本

hello.s编译的汇编文本

hello.o可重定位目标文件

hello链接后的可执行目标文件

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值