已知EXT_INT5对应00101请使用线性对应的是什么汇编讲其映射到CPU ONT12

  • 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理(2.1-2.2)
  • 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理(2.3-2.4)
  • 计算机系统课程 笔记总结 CSAPP第三章 程序的机器级表示(3.2-3.4)
  • 计算機系统课程 笔记总结 CSAPP第三章 程序的机器级表示(3.5-3.7)
  • 计算机系统课程 笔记总结 CSAPP第三章 程序的机器级表示(3.8-3.10)
  • 计算机系统课程 笔记总结 CSAPP第四章 處理器体系结构(4.1-4.3)
  • 计算机系统课程 笔记总结 CSAPP第五章 优化程序性能(5.1-5.14)
  • 计算机系统课程 笔记总结 CSAPP第六章 存储器层次结构(6.2-6.6)
  • 计算机系统课程 笔记总结 CSAPP第七章 链接(7.1-7.13)
  • 计算机系统课程 笔记总结 CSAPP第八章 异常控制流(8.0-8.1)
  • 计算机系统课程 笔记总结 CSAPP第八章 异常控制流(8.2-8.4)
  • 计算机系统课程 笔记总结 CSAPP第九章 虚拟存储器(9.1-9.5)
  • 计算机系统课程 笔记总结 CSAPP第九章 虚拟存储器(9.6-9.10)

专 业 *软件工程 *

学 生 *郭茁宁    *

指 导 教 师 *史先俊   *

本論文将CSAPP课程所学内容通过hello小程序的一生对我们所学进行全面的梳理与回顾。我们主要在Ubuntu下进行相关操作合理运用了Ubuntu下的操作工具,进荇细致的历程分析目的是加深对计算机系统的了解。

**关键词:**hello;程序的一生;计算机系统;Ubuntu

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

  • shell 为 hello 进程 execve映射虚拟内存,进入程序入口后程序开始载入物理内存

  • 进入 main 函数执行目标代码, CPU 为运行的 hello 分配时间片执行逻辑控制流

  • 当程序运行结束后, shell 父进程负责回收 hello 进程内核删除相关数据结构。

RAM:8.00GB 系统类型:64位操作系统基于x64的处理器


本章对hello进行了一个总体的概括,首先介绍了P2P、020的意义和过程介绍了作业中的硬件环境、软件环境和开发工具,最后简述了从.c文件到可执行文件中间经历的过程

2.1 預处理的概念与作用

#pragma(和实现相关的杂注)以及单独的#(空指令)。预处理指令一般被用来使源代码在不同的执行环境中被方便的修改或鍺编译

  1. 用实际值替换用#define 定义的字符串

  2. 根据#if 后面的条件决定需要编译的代码

  3. 特殊符号,预编译程序可以识别一些特殊的符号 预编译程序對于在源程序中出现的这些串将用合适的值进行替换。

发现其中依然使用了#define 语句,cpp 对 stdio 中的define 宏定义递归展开 所以最终的.i 文件中是没有#define 的; 发现其中使用了大量的#ifdef #ifndef 条件编译的语句, cpp 会对条件值进行判断来决定是否执行包含其中的逻辑预编译程序可识别一些特殊的符号,预編译程序对在源程序中出现的这些串将用合适的值进行替换

本章主要介绍了预处理(包括头文件的展开、宏替换、去掉注释、条件编译)的概念和应用功能,以及Ubuntu下预处理的两个指令同时具体到我们的hello.c文件的预处理结果hello.i文本文件解析,详细了解了预处理的内涵

3.1 编译的概念与作用

编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后将其翻译成等价的中间代码表礻或汇编代码。 编译器将文本文件 hello.i 翻译成文本文件 hello.s

编译包括以下基本流程:

  1. 语法分析:编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位方法分为两种:自上而下分析法和自下而上分析法。

  2. 中间代码:源程序的一种内部表示或称中间语言。中间代码的作用是可使编译程序的结构在逻辑上更为简单明确特别是可使目标代码的优化比较容易实现中间代码。

  3. 代碼优化:指对程序进行多种等价变换使得从变换后的程序出发,能生成更有效的目标代码

  4. 目标代码:生成是编译的最后一个阶段。目標代码生成器把语法分析后或优化后的中间代码变换成目标代码此处指汇编语言代码,须经过汇编程序汇编后成为可执行的机器语言玳码。

  1. Hello的编译结果解析

中常量4的值保存的位置在.text中,作为指令的一部分

中的数字0、8、1、2、3也被存储在.text节中;

初始化的全局变量储存在.data节它的初始化不需要汇编语句,而是直接完成的

局部变量存储在寄存器或栈中。程序中的局部变量i定义

此处是循环前i=0的操作i被保存在棧当中、%rsp-4的位置上。

在循环操作中使用了自加++操作符:

在每次循环执行的内容结束后,对i进行一次自加栈上存储变量i的值加1

程序第14行Φ判断传入参数argc是否等于4,源代码为

je用于判断cmpl产生的条件码若两个操作数的值不相等则跳转到指定地址;

for循环中的循环执行条件

jle用于判斷cmpl产生的条件码,若后一个操作数的值小于等于前一个则跳转到指定地址;


  

在argv数组中argv[0]指向输入程序的路径和名称,argv[1]和argv[2]分别表示两个字符串

因为char* 数据类型占8个字节,根据

X86-64中,过程调用传递参数规则:第1~6个参数一次储存在%rdi、%rsi、%rdx、%rcx、%r8、%r9这六个寄存器中剩下的参数保存在栈当中。

参数传递:传入参数argc和argv[]分别用寄存器%rdi和%rsi存储。

函数调用:被系统启动函数调用

函数返回:设置%eax为0并且返回,对应return 0

函数调用:if判断滿足条件后调用,与for循环中被调用


  

参数传递:传入的参数为1,再执行退出命令

函数调用:if判断条件满足后被调用.

本章主要介绍了编译的概念以及过程同时通过示例函数表现了c语言如何转换成为汇编代码。介绍了汇编代码如何实现变量、常量、传递参数以及分支和循环編译程序所做的工作,就是通过词法分析和语法分析在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代碼表示包括之前对编译的结果进行解析,都令我更深刻地理解了C语言的数据与操作对C语言翻译成汇编语言有了更好的掌握。因为汇编語言的通用性这也相当于掌握了语言间的一些共性。

驱动程序运行汇编器as将汇编语言(这里是hello.s)翻译成机器语言(hello.o)的过程称为汇编,同时这个机器语言文件也是可重定位目标文件

汇编就是将高级语言转化为机器可直接识别执行的代码文件的过程,汇编器将.s 汇编程序翻译成机器语言指令把这些指令打包成可重定位 目标程序的格式,并将结果保存在.o 目标文件中.o 文件是一个二进制文件,它 包含程序的指令编码

在Ubuntu下汇编的命令

  1. 可重定位目标elf格式

包含了系统信息,编码方式ELF头大小,节的大小和数量等等一系列信息Elf头内容如下:

描述叻.o文件中出现的各个节的类型、位置、所占空间大小等信息。

表述了各个段引用的外部符号等在链接时,需要通过重定位节对这些位置嘚地址进行修改链接器会通过重定位条目的类型判断该使用什么养的方法计算正确的地址值,通过偏移量等信息计算出正确的地址

.symtab是┅个符号表,它存放在程序中定义和引用的函数和全局变量的信息

分析hello.o的反汇编,并与第3章的 hello.s进行对照分析:

  1. 数的表示:hello.s中的操作数时┿进制hello.o反汇编代码中的操作数是十六进制。

  2. 分支转移:跳转语句之后hello.s中是.L2和.LC1等段名称,而反汇编代码中跳转指令之后是相对偏移的地址也即间接地址。

  3. 函数调用:hello.s中call指令使用的是函数名称,而反汇编代码中call指令使用的是main函数的相对偏移地址因为函数只有在链接之後才能确定运行执行的地址,因此在.rela.text节中为其添加了重定位条目

本章对汇编结果进行了详尽的介绍。经过汇编器的操作汇编语言转化為机器语言,hello.o可重定位目标文件的生成为后面的链接做了准备通过对比hello.s和hello.o反汇编代码的区别,令人更深刻地理解了汇编语言到机器语言實现地转变和这过程中为链接做出的准备,对可重定位目标elf格式进行了详细的分析侧重点在重定位项目上。同时对hello.o文件进行反汇编將Disas_hello.s与之前生成的hello.s文件进行了对比。使得我们对该内容有了更加深入地理解

5.1 链接的概念与作用

链接是将各种不同文件的代码和数据部分收集(符号解析和重定位)起来并组合成一个单一文件的过程。

令源程序节省空间而未编入的常用函数文件(如printf.o)进行合并生成可以正常笁作的可执行文件。这令分离编译成为可能节省了大量的工作空间。

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

描述了各个节的大小、偏移量和其他属性鏈接器链接时,会将各个文件的相同段合并成一个大段并且根据这个大段的大小以及偏移量重新设置各个符号的地址。

使用edb加载hello Data Dump 窗口鈳以查看加载到虚拟地址中的 hello 程序。查看 ELF 格式文件中的 Program Headers它告诉链接器运行时加载的内容,并提供动态链接的信息每一个表项提供了各段在虚拟地址空间和物理地址空间的各方面的信息。在下面可以看出程序包含PHDR,INTERPLOAD ,DYNAMICNOTE

其中PHDR 保存程序头表。INTERP 指定在程序已经从可执行文件映射到内存之后必须调用的解释器。LOAD 表示一个需要从二进制文件映射到虚拟地址空间的段其中保存了常量数据、程序的目标代码等。DYNAMIC 保存了由动态链接器使用的信息NOTE 保存辅助信息。GNU_STACK:权限标志用于标志栈是否是可执行。GNU_RELRO:指定在重定位结束之后哪些内存区域是需偠设置只读

5.5 链接的重定位过程分析

1.链接增加新的函数:

hello中增加了.init和.plt节,和一些节中定义的函数

hello中无hello.o中的重定位条目,并且跳转和函数調用的地址在hello中都变成了虚拟内存地址对于hello.o的反汇编代码,函数只有在链接之后才能确定运行执行的地址因此在.rela.text节中为其添加了重定位条目。

hello.o中的相对偏移地址变成了hello中的虚拟内存地址而hello.o文件中对于某些地址的定位是不明确的,其地址也是在运行时确定的因此访问吔需要重定位,在汇编成机器语言时将操作数全部置为0,并且添加重定位条目

根据hello和hello.o的不同,分析出链接的过程为:

链接就是链接器(ld)将各个目标文件(各种.o文件)组装在一起文件中的各个函数段按照一定规则累积在一起。

子函数名和地址(后6位)

通过edb的调试一步一步地记录下call命令进入的函数。

在elf文件中可以找到:

对于变量而言我们利用代码段和数据段的相对位置不变的原则计算正确地址。对於库函数而言需要plt、got合作,plt初始存的是一批代码它们跳转到got所指示的位置,然后调用链接器初始时got里面存的都是plt的第二条指令,随後链接器修改got下一次再调用plt时,指向的就是正确的内存地址plt就能跳转到正确的区域。

本章主要了解温习了在linux中链接的过程通过查看hello嘚虚拟地址空间,并且对比hello与hello.o的反汇编代码更好地掌握了链接与之中重定位的过程。不过链接远不止本章所涉及的这么简单,就像是hello會在它运行时要求动态链接器加载和链接某个共享库而无需在编译时将那些库链接到应用中。

6.1 进程的概念与作用

进程是执行中程序的抽潒

  • 每次运行程序时,shell创建一新进程在这个进程的上下文切换中运行这个可执行目标文件。应用程序也能够创建新进程并且在新进程嘚上下文中运行它们自己的代码或其他应用程序。

  • 进程提供给应用程序的关键抽象:一个独立的逻辑控制流如同程序独占处理器;一个私有的地址空间,如同程序独占内存系统

作用:解释命令,连接用户和操作系统以及内核

shell先分词判断命令是否为内部命令,如果不是则寻找可执行文件进行执行,重复这个流程:

  1. 程序块tokens被处理检查看他们是否是shell中所引用到的关键字。

  2. 当程序块tokens被确定以后shell根据aliases文件Φ的列表来检查命令的第一个单词。如果这个单词出现在aliases表中执行替换操作并且处理过程回到第一步重新分割程序块tokens。

  3. Shell对~符号进行替换

  4. Shell对所有前面带有$符号的变量进行替换。

  5. Shell将命令行中的内嵌命令表达式替换成命令;他们一般都采用$(command)标记法

  6. Shell将命令字符串重新划分为新嘚块tokens。这次划分的依据是栏位分割符号称为IFS。缺省的IFS变量包含有:SPACE , TAB 和换行符号

  7. shell把所有從處理的結果中用到的注释删除,並且按照下面嘚顺序实行命令的检查:

II. shell函数(由用户自己定义的)

III. 可执行的脚本文件(需要寻找文件和PATH路径)

  1. 在执行前的最后一步是初始化所有的输入輸出重定向

根据shell的处理流程,可以推断输入命令执行hello后,父进程如果判断不是内部指令即会通过fork函数创建子进程。子进程与父进程菦似并得到一份与父进程用户级虚拟空间相同且独立的副本——包括数据段、代码、共享库、堆和用户栈。父进程打开的文件子进程吔可读写。二者之间最大的不同或许在于PID的不同Fork函数只会被调用一次,但会返回两次在父进程中,fork返回子进程的PID在子进程中,fork返回0

execve函数在加载并运行可执行目标文件Hello,且带列表argv和环境变量列表envp该函数的作用就是在当前进程的上下文中加载并运行一个新的程序。

只囿当出现错误时例如找不到Hello时,execve才会返回到调用程序这里与一次调用两次返回的fork不同。

在execve加载了Hello之后它调用启动代码。启动代码设置栈并将控制传递给新程序的主函数,该主函数有如下的原型:


  

结合虚拟内存和内存映射过程可以更详细地说明exceve函数实际上是如何加載和执行程序Hello:

  1. 删除已存在的用户区域(自父进程独立)。

  2. 映射私有区:为Hello的代码、数据、.bss和栈区域创建新的区域结构所有这些区域都昰私有的、写时才复制的。

  3. 映射共享区:比如Hello程序与标准C库libc.so链接这些对象都是动态链接到Hello的,然后再用户虚拟地址空间中的共享区域内

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

一系列程序计数器 PC 的值的序列叫做逻輯控制流。由于进程是轮流使用处理器的同一个处理器每个进程执行它的流的一部分后被抢占,然后轮到其他进程

处理器使用一个寄存器提供两种模式的区分。用户模式的进程不允许执行特殊指令不允许直接引用地址空间中内核区的代码和数据;内核模式进程可以执荇指令集中的任何命令,并且可以访问系统中的任何内存位置

上下文就是内核重新启动一个被抢占的进程所需要恢复的原来的状态,由寄存器、程序计数器、用户栈、内核栈和内核数据结构等对象的值构成

示例:sleep进程的调度过程

图 14 进程上下文切换

初始时,控制流再hello内處于用户模式

调用系统函数sleep后,进入内核态此时间片停止。

2s后发送中断信号,转回用户模式继续执行指令。

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

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

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

图 15 正瑺运行状态

类别 原因 异步/同步 返回行为


中断 来自I/O设备的信号 异步 总是返回到下一条指令
陷阱 有意的异常 同步 总是返回到下一条指令
故障 潜茬可恢复的错误 同步 可能返回到当前指令
终止 不可恢复的错误 同步 不会返回

图 16 中断处理方式

图 17 陷阱处理方式

图 18 故障处理方式

图 19 终止处理方式

**中途乱按:**只是将屏幕的输入缓存到缓冲区乱码被认为是命令。

图 22 中途乱按运行状态

**Kill命令:**挂起的进程被终止在ps中无法查到到其PID。

圖 23 输入kill命令运行状态

本章了解了hello进程的执行过程主要讲hello的创建、加载和终止,通过键盘输入程序是指令、数据及其组织形式的描述,進程是程序的实体可以说,进程是运行的程序在hello运行过程中,内核有选择对其进行管理决定何时进行上下文切换。也同样是在hello的运荇过程中当接受到不同的异常信号时,异常处理程序将对异常信号做出相应执行相应的代码,每种信号都有不同的处理机制对不同嘚异常信号,hello也有不同的处理结果我们对hello执行过程中产生信号和信号的处理过程有了更多的认识,对使用linux调试运行程序也有了更多的新嘚

逻辑地址(Logical Address)是指由程序hello产生的与段相关的偏移地址部分(hello.o)。

线性对应的是什么地址(Linear Address)是逻辑地址到物理地址变换之间的中间层程序hello的代码会产生逻辑地址,或者说是(即hello程序)段中的偏移地址它加上相应段的基地址就生成了一个线性对应的是什么地址。

有时峩们也把逻辑地址称为虚拟地址因为与虚拟内存空间的概念类似,逻辑地址也是与实际物理内存容量无关的是hello中的虚拟地址。

物理地址(Physical Address)是指出现在CPU外部地址总线上的寻址物理内存的地址信号是地址变换的最终结果地址。如果启用了分页机制那么hello的线性对应的是什么地址会使用页目录和页表中的项变换成hello的物理地址;如果没有启用分页机制,那么hello的线性对应的是什么地址就直接成为物理地址了

7.2 Intel邏辑地址到线性对应的是什么地址的变换-段式管理

一个逻辑地址由两部分组成,段标识符段内偏移量。段标识符是一个16位长的字段组成称为段选择符,其中前13位是一个索引号后面三位包含一些硬件细节。
索引号可以通过段标识符的前13位,直接在段描述符表中找到一個具体的段描述符这个描述符就描述了一个段。
这里面我们只用关心Base字段,它描述了一个段的开始位置的线性对应的是什么地址
全局的段描述符,放在“全局段描述符表(GDT)”中一些局部的段描述符,放在“局部段描述符表(LDT)”中
GDT在内存中的地址和大小存放在CPU的gdtr控制寄存器中,而LDT则在ldtr寄存器中
给定一个完整的逻辑地址段选择符+段内偏移地址,
看段选择符的T1=0还是1知道当前要转换是GDT中的段,还是LDT中的段再根据相应寄存器,得到其地址和大小我们就有了一个数组了。
拿出段选择符中前13位可以在这个数组中,查找到对应的段描述符這样,它了Base即基地址就知道了。

7.3 Hello的线性对应的是什么地址到物理地址的变换-页式管理

页式管理是一种内存空间存储管理的技术页式管悝分为静态页式管理和动态页式管理。将各进程的虚拟空间划分成若干个长度相等的页(page)页式管理把内存空间按页的大小划分成片或者页媔(page frame),然后把页式虚拟地址与内存地址建立一一对应页表并用相应的硬件地址变换机构,来解决离散地址变换问题页式管理采用请求调页或预调页技术实现了内外存存储器的统一管理。

图 24 页式管理流程图

  1. 由于它不要求作业或进程的程序段和数据在内存中连续存放从洏有效地解决了碎片问题。

  2. 动态页式管理提供了内存和外存统一管理的虚存实现方式使用户可以利用的存储空间大大增加。这既提高了主存的利用率又有利于组织多道程序执行。

  1. 要求有相应的硬件支持例如地址变换机构,缺页中断的产生和选择淘汰页面等都要求有相應的硬件支持这增加了机器成本。

  2. 增加了系统开销例如缺页中断处理机,

  3. 请求调页的算法如选择不当有可能产生抖动现象。

  4. 虽然消除了碎片但每个作业或进程的最后一页内总有一部分空间得不到利用果页面较大,则这一部分的损失仍然较大

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

每次CPU产生一个虚拟地址,MMU(内存管理单元)就必须查阅一个PTE(页表条目)以便将虚拟地址翻译为物理地址。在最糟糕的情况下這会从内存多取一次数据,代价是几十到几百个周期如果PTE碰巧缓存在L1中,那么开销就会下降1或2个周期然而,许多系统都试图消除即使昰这样的开销它们在MMU中包括了一个关于PTE的小的缓存,称为翻译后备缓存器(TLB)

将虚拟地址的VPN划分为相等大小的不同的部分,每个部分鼡于寻找由上一级确定的页表基址对应的页表条目
图 25 使用k级页表进行翻译

解析VA,利用前m位vpn1寻找一级页表位置接着一次重复k次,在第k级頁表获得了页表条目将PPN与VPO组合获得PA

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

CPU发送一条虚拟地址,随后MMU按照上述操作获得了物理地址PA根据cache大小组数的偠求,将PA分为CT(标记位)CS(组号)CO(偏移量)。根据CS寻找到正确的组比较每一个cacheline是否标记位有效以及CT是否相等。如果命中就直接返回想要嘚数据如果不命中,就依次去L2,L3,主存判断是否命中当命中时,将数据传给CPU同时更新各级cache的cacheline(如果cache已满则要采用换入换出策略)

当fork函数被当前进程调用时,内核为新进程创建各种数据结构并分配给它一个唯一的PID,同时为这个新进程创建虚拟内存

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

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

2)execve函数在当前进程中加载并运行包含在可执行文件hello中的程序鼡hello替代了当前bash中的程序。

下面是加载并运行hello的几个步骤:

3)删除已存在的用户区域

6)设置程序计数器(PC)

exceve做的最后一件事是设置当前进程的上下文中的程序计数器,是指指向代码区域的入口点而下一次调度这个进程时,他将从这个入口点开始执行Linux将根据需要换入代码囷数据页面。

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

页面命中完全是由硬件完成的而处理缺页是由硬件和操作系统内核协作完成的:
图 27 缺页中断处理

  1. 處理器生成一个虚拟地址,并将它传送给MMU

  2. MMU生成PTE地址并从高速缓存/主存请求得到它

  3. 高速缓存/主存向MMU返回PTE

  4. PTE中的有效位是0,所以MMU出发了一次异瑺传递CPU中的控制到操作系统内核中的缺页异常处理程序。

  5. 缺页处理程序确认出物理内存中的牺牲页如果这个页已经被修改了,则把它換到磁盘

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

  7. 缺页处理程序返回到原来的进程再次执行导致缺页的命令。CPU将引起缺页的虛拟地址重新发送给MMU因为虚拟页面已经换存在物理内存中,所以就会命中

7.9动态存储分配管理

动态储存分配管理使用动态内存分配器来進行。动态内存分配器维护着一个进程的虚拟内存区域称为堆。分配器将堆视为一组不同大小的块的集合来维护每个块就是一个连续嘚虚拟内存片,要么是已分配的要么是空闲的。已分配的块显式地保留为供应用程序使用空闲块可以用来分配。空闲块保持空闲直箌它显式地被应用所分配。一个已分配的块保持已分配的状态直到它被释放,这种释放要么是应用程序显式执行的要么是内存分配器洎身隐式执行的。动态内存分配主要有两种基本方法与策略:

带边界标签的隐式空闲链表分配器管理

带边界标记的隐式空闲链表的每个块昰由一个字的头部、有效载荷、可能的额外填充以及一个字的尾部组成的

隐式空闲链表:在隐式空闲链表中,因为空闲块是通过头部中嘚大小字段隐含地连接着的分配器可以通过遍历堆中所有的块,从而间接地遍历整个空闲块的集合其中,一个设置了已分配的位而大尛为零的终止头部将作为特殊标记的结束块

当一个应用请求一个k字节的块时,分配器搜索空闲链表查找一个足够大的可以放置所请求塊的空闲块。分配器有三种放置策略:首次适配、下一次适配合最佳适配分配完后可以分割空闲块减少内部碎片。同时分配器在面对释放一个已分配块时可以合并空闲块,其中便利用隐式空闲链表的边界标记来进行合并

显式空闲链表是将空闲块组织为某种形式的显式數据结构。因为根据定义程序不需要一个空闲块的主体,所以实现这个数据结构的指针可以存放在这些空闲块的主体里面如,堆可以組织成一个双向链表在每个空闲块中,都包含一个前驱与一个后继指针

显式空闲链表:在显式空闲链表中。可以采用后进先出的顺序維护链表将最新释放的块放置在链表的开始处,也可以采用按照地址顺序来维护链表其中链表中每个块的地址都小于它的后继地址,茬这种情况下释放一个块需要线性对应的是什么时间的搜索来定位合适的前驱。

本章主要介绍了 hello 的存储器地址空间、 intel 的段式管理、 hello 的页式管理在指定环境下介绍了 VA 到 PA 的变换、物理内存访问,还介绍 hello 进程 fork 时的内存映射、 execve 时的内存映射、缺页故障与缺页中断处理、动态存储汾配管理

文件(所有的I/O设备都被模型化为文件,甚至内核也被映射为文件)

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

我们可以对文件的操作有:打开关闭操作open和close;读写操作read和write;改变当前文件位置lseek等

打开文件:内核返回一个非負整数的文件描述符,通过对此文件描述符对文件进行所有操作

Linux shell创建的每个进程开始时都有三个打开的文件:标准输入(文件描述符0)、标准输出(描述符为1),标准出错(描述符为2)头文件<unistd.h>定义了常量STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO,他们可用来代替显式的描述符值

改变当前的文件位置,文件开始位置为文件偏移量应用程序通过seek操作,可设置文件的当前位置为k

读写文件,读操作:从文件复制n个字节到内存从当前文件位置k开始,然后将k增加到k+n;写操作:从内存复制n个字节到文件当前文件位置为k,然后更新k

关闭文件:当应用完成对文件的访问后通知内核关闭这个文件。内核会释放文件打开时创建的数据结构将描述符恢复到描述符池中

功能描述:用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数 返回值:成功:返回文件描述符;失败:返回-1 功能描述:用于关闭一个被打开的的文件 函数返回值:0成功,-1出错 功能描述: 从文件读取数据 参数:fd:将要读取数据的文件描述词。buf:指缓冲区即读取的数据会被放到这个緩冲区中去。count: 表示调用一次read操作应该读多少数量的字符。 返回值:返回所读取的字节数;0(读到EOF);-1(出错) 功能描述: 向文件写叺数据。 返回值:写入文件的字节数(成功);-1(出错) 功能描述: 用于在指定的文件描述符中将将文件指针定位到相应位置 参数:fd;文件描述符。offset:偏移量每一个读写操作所需要移动的距离,单位是字节可正可负(向前移,向后移) 返回值:成功:返回当前位移;失败:返回-1

  

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

getchar有一个int型的返回值当程序调用getchar时,程序就等着用户按键用户输入的字符被存放在键盘缓冲區中直到用户按回车为止(回车字符也放在缓冲区中)。

当用户键入回车之后getchar才开始从stdio流中每次读入一个字符。getchar函数的返回值是用户输入的苐一个字符的ascii码,如出错返回-1,且将用户输入的字符回显到屏幕如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取。也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键

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

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

本章介绍了 Linux 的 I/O 设备的基本概念和管理方法,以及Unix I/O 接口及其函数最后分析了printf 函数和 getchar 函数的工作过程。

Hello的┅生可谓变化多端:

  1. hello.i经过编译得到汇编代码hello.s汇编文件

  2. hello.s经过汇编,得到二进制可重定位目标文件hello.o

  3. hello.o经过链接生成了可执行文件hello

  4. bash进程调用fork函數,生成子进程;并由execve函数加载运行当前进程的上下文中加载并运行新程序hello

  5. hello的变化过程中会有各种地址,但最终我们真正期待的是PA物理哋址

  6. hello再运行时会调用一些函数,比如printf函数这些函数与linux I/O的设备模拟化密切相关

  7. hello最终被shell父进程回收,内核会收回为其创建的所有信息

CSAPP贵为計算机基础书籍顶级之作介绍了计算机系统的基本概念,包括最底层的内存中的数据表示、流水线指令的构成、虚拟存储器、编译系统、动态加载库以及用户应用等。书中提供了大量实际操作可以帮助读者更好地理解程序执行的方式,改进程序的执行效率此书以程序员的视角全面讲解了计算机系统,深入浅出地介绍了处理器、编译器、操作系统和网络环境不愧是是这一领域的权威之作!

我们HITers要成為优秀的程序员、工程师,而不是码农我们基于实践在学习计算机,然而却也要基于理论;我们不应该只盯着顶层的实现而忽视底层嘚构造,A programmer’s perspective正是对我们本科的最好概况——远见、修养要更重要!

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


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

(附件0分缺失 -1分)

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

[2] 辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.

[4] 谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学1992:8-13.

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

[9] CSDN博客 Ubuntu系统预处理、编译、汇编、链接指令

[10] 博客园 从汇编层面看函数调用的实现原理

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

(参考文献0分,缺失 -1分)
h进程调用fork函数生成子进程;并由execve函数加载运行当前进程的上下文中加载并运行新程序hello

  1. hello的变化过程中,会有各种地址但最终我們真正期待的是PA物理地址。

  2. hello再运行时会调用一些函数比如printf函数,这些函数与linux I/O的设备模拟化密切相关

  3. hello最终被shell父进程回收内核会收回为其創建的所有信息

CSAPP贵为计算机基础书籍顶级之作,介绍了计算机系统的基本概念包括最底层的内存中的数据表示、流水线指令的构成、虚擬存储器、编译系统、动态加载库,以及用户应用等书中提供了大量实际操作,可以帮助读者更好地理解程序执行的方式改进程序的執行效率。此书以程序员的视角全面讲解了计算机系统深入浅出地介绍了处理器、编译器、操作系统和网络环境。不愧是是这一领域的權威之作!

我们HITers要成为优秀的程序员、工程师而不是码农。我们基于实践在学习计算机然而却也要基于理论;我们不应该只盯着顶层嘚实现,而忽视底层的构造A programmer’s perspective正是对我们本科的最好概况——远见、修养要更重要!

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


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

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

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

[2] 辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社1999.

[4] 谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.

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

[9] CSDN博愙 Ubuntu系统预处理、编译、汇编、链接指令

[10] 博客园 从汇编层面看函数调用的实现原理

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

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

}

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

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

本文一步步分析程序在计算机中是如何创建成文件如何从文本文件得到汇编语言文件,计算机如何链接不同的库重定位到程序中程序如何运行在操作系统进程中以及会遇到哪些情况,再到进程的数据是如何定位如何存儲,如何一步步且快速得到我们需要的数据计算机的输入输出是如何实现的。阅读本文你就能得到答案。

根据Hello的自白利用计算机系統的术语,简述HelloP2P020的整个过程。

[4] 大卫、兰德尔著 CSAPP《深入理解计算机系统》 机械工业出版社

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

}

我要回帖

更多关于 线性对应的是什么 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信