内存管理学习笔记

数据结构中的栈和堆

栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为先进后出表。

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。

完全二叉树

一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
所以完全二叉树是左对齐的。

内存管理

程序的装入

绝对装入、可重定位装入方式、动态运行时的装入方式
绝对装入:单道程序中,用户可以知道装入的地址,绝对地址在编译或汇编时给出,也可由用户赋予。
可重定位:程序的起始地址通常都是从0开始,是相对于自身的位置的,多道程序就不再能用自己的地址。程序装入内存的地方作为基地址,再加上逻辑地址就能得到绝对地址。因为地址变换通常时在进程装入时一次完成的,以后不再改变,故称静态重定位。
运行时装入:上面的可重定位虽然可以将进程装入到内存的任意允许的地方,但不允许程序运行时在内存中移动位置。因为程序在内存中的移动,意味着物理物理位置发生了变化。
动态运行时的装入程序在把装入模块装入内存后,并不立即把装入模块中的逻辑地址转换为物理地址,而是把这种地址转换推迟到程序真正要执行时才进行

连续分配存储管理方式

单一连续分配、固定分区分配
单一连续分配:仅有一道用户程序
固定分区分配:分区大小相等、分区大小不等

内存分配

将分区按大小排队、并建立分区表,其中各表包括分区的起始地址、大小及状态。当有一用户程序要装入时,由内存分配程序依据用户程序的大小检索,找出满足要求、尚未被分配的分区,分配给程序。然后更新分区表状态。

动态分区分配

数据结构
  • 空闲分区表
  • 空闲分区链
分区分配操作

分配内存,如果分配后分区太小,则产生了内部碎片,否则继续分配给其他内存,返回给调用者分配的首地址
回收内存三种情况:
1.与一个空闲分区临界
2.与上下俩个空闲分区临界
3.不临界

基于顺序搜索的动态分区分配算法

1.首次适应:每次从分区表或链表头部开始找合适分区。倾向利用低地址部分的空闲分区,从而保留了高地址的大空闲区,为大作业留下了地方,缺点是低址会产生很多小碎片无法利用。
2.循环首次适应:每次从上次找到的空闲分区开始找。这样使得分区分布均匀,但没有大分区
3.最佳适应:将分区不再用地址排列,用大小排列。然后利用首次适应方法找分区,也会留下难以利用的许多小分区
4。最坏适应。策略相反,每次找出分区最大的去分配,以导致没有大的分区
以上分配不是按进程为单位,而是作业为单位

基于索引搜索的动态分区分配算法

1.快速适应算法
将分区根据不同大小进行分类,每一类分区大小一致,建立空闲分区链表,内存中设立一个大的整体索引管理表,每个索引表项对应了一种空闲分区类型,并记录了该类型空闲分区链表表头的头指针,划分是根据常用空间大小,如4kb、8kb,特殊大小分区可以新建链,也可以归入,比如7kb可以归入8kb的链中。分配方式就是找能容纳它的最小分区,它不会分割,因为分配是以进程为单位的。不会产生外部碎片、查找效率高。缺点是为了有效合并分区,归还时比较复杂,系统开销大。一个分区只属于一个进程,存在浪费产生内部碎片
2.伙伴系统
分区大小固定为2的k次幂,不管是已经分配还是未分配。和上面差不多将为分配的区根据大小分类,建立双向链表,当需要为一个进程分配n的空间时,计算一个i值,使得 2的i次方-1<n<=2的i次方 ,然后在空闲分区大小为2的次方的空闲分区链表里找,找到就分配,找不到则在2的i+1次方的空闲分区里找,若存在,就将它平分,一半加入到2的i次方链表,另一半继续用作分配。找不到i继续加一,直到为最大值。
3.哈希算法
也是将空闲分区根据大小进行分类,建立链表,在为进程分配空间时,需要一张管理索引表。如果此时分区分类很多,则索引表表项也就多,增加了搜索的时间开销。
哈希算法就是利用哈希的快速查找优点。以及分布规律,构造一张以空闲大小为关键字的哈希表,分配时,根据所需大小,通过哈希计算,就得到了空闲分区链表。

动态可重定位分配

连续分配的特点就是,一个系统或程序必须被装入一片连续的内存空间中,所以会产生碎片,分区的大小也会变小,缺乏较大的空闲空间。
1.紧凑
紧凑的办法是将所有已分配的内存拼接到一起。但是他们在内存中的地址发生了变化,每次紧凑后都必须重定位,相当麻烦。
2.动态重定位
动态重定位和静态重定位不同的是,静态重定位仅在程序第一次装入时改变了指令和数据地址。动态重定位是作业装入内存仍然是相对地址,而转换过程推迟到了指令真正执行时。增加一个重定位寄存器,用它来存放程序在内存的起始地址,这样以来,系统对内存进行“紧凑”,仅修改寄存器的值即可,在转换时,使用新地址。
2。动态重定位分区分配算法
与动态分区分配算法基本相同,增加紧凑功能

分页存储管理方式

连续分配会产生许多碎片,虽然紧凑能一定程度解决问题,但为之付出很大开销,产生离散分配的思想
1.分页存储管理方式
2.分段存储管理方式
3.段页式存储管理方式

分页存储管理的基本方法

1.页面和物理块
分页存储管理将进程的逻辑空间地址分成若干个页,并为各页加以编号,从0开始,如第0页,第1页等。相应的,也把内存的物理地址空间分成若干个块,同样编号,在为进程分配内存时,以块为单位,将若干个页方到不相邻的物理块中,由于进程的最后一页经常装不满一块,形成了许多不可利用的碎片,称为“页内碎片”。
2.页面大小
过小,进程占用多个页面,占用大量内存,降低页面换入换出的效率。过大,使得页内碎片增大,因此,页面的大小应选择适中,2的幂,1到8kb。
3.地址结构
由俩部分组成,页号和位移量。
这么多页需要一个表来管理
4.页表
系统为每个进程建立了一张页面映像表,简称页表,页表中每一项纪录了页在内存中对应的物理块号,还有存取控制字段。

地址变换机构

负责将逻辑地址转换为内存空间中的物理地址。将逻辑地址中的页号转换成内存中的物理块号。
1.基本的地址变换机构
页表由一组专门的寄存器来实现。 页表大多驻留在内存中,在系统中设置一个页表寄存器PTR,在其中存放页表在内存的始地址和页表的长度,进程未执行时,页表的始址存放在本进程的PCB中,当调度程序调度到某进程时,才将这俩个数据装入页表寄存器中。
查找操作:
当进程要访问某个逻辑地址,分页地址变换机构会自动地将有效地址( 相对地址)分为页号和页内地址俩部分,再以页号为索引去检索页表。在执行检索之前,先将页号与页表长度进行比较,如果页号大小或等于页表长度,则表示本次访问的地址已超越进程的地址空间,产生越界中断。若未出现错误,则将页表始址与页号和页表项长度的乘积相加,得到该表项在页表中的位置。
2.快表
基础的寻址需要俩次,首先访问内存的页表,转换成物理地址,然后去访问物理地址。快表相当于是缓存了第一步的访问,增设了一个具有并行查寻能力的特殊高速缓存器,又称为联想缓存器TLB。第一次访问的时候是把页号与缓存器中的页号匹配,从而直接找到物理块号

俩级和多级页表

俩级页表,即将上述的页表再进行分页。由于地址空间巨大,所以页表的占用内存是很大的,难以找到连续的大内存。我们将页表也离散的分配到物理内存中,再次分页,建立外层页表,进行访问。要减少内存占用,需要对外层页表的寄存器增设一个标志位,判断哪些页在内存中
在这里插入图片描述
多级页表在这里插入图片描述

反置页表

为每一个物理块设置一个页表项,按照物理块的编号排序,其中的内容则是页号和其所属的进程的标示符
反置表的地址变换
根据进程标示符和页号去检索反置页表。如果检索到与之匹配的页表项,则该页表项中的序号i便是该页所在的物理块号。可用该块号与页内地址一起构成物理地址送内存地址寄存器。

分段存储管理

通常程序被分为主程序段、子程序段、数据段、栈段等,每个段大多是一个独立的逻辑单位,实现和满足信息共享、信息保护、动态链接以及信息的动态增长需要等,以段为基本单位。跟符合用户和程序员的需要

分段系统基本原理

在分段存储管理方式中,作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息。段名和段内地址。整个作业被分成多个段,呈现二维特性,即每个段既包含了一部分地址空间,又标示了逻辑关系。其逻辑地址由段号(段名)和段地址组成。

段表

动态分区中,系统为整个进程分配一个连续的内存空间,而在分段式存储管理系统中,则是为每个分段分配一个连续的分区,进程中的各个段,可以离散地装入不同的分区中。为保证程序能正常运行,就必须能从物理内存中找出每个逻辑段所对应的位置。为此,,类似于分页系统,需为每个进程建立一张段映射表,简称段表。每个段在表中占有一个表项,其中记录了该段在内存中的起始地址和段长度

地址变换机构

为了实现进程从逻辑地址到物理地址的变换功能,在系统中设置了段表寄存器,用于存放表始地址和段表长度TL。 先判断段号是否超过了段表的长度,超过了产生越界中断信号。若未越界,根据段表的始地址和该段的段号,计算出该段对应段表项的位置,从中读出该段在内存起始地址。然后检查段内地址是否超过了段长,若未越界,将该段的基地址与段内地址相加,即可得到物理地址。

分段和分页的不同

1.页是信息的基本单位,分页存储是为了消除内存的外零头 ,提高内存利用率,它的产生是系统为了管理内存的需要。而段是信息的逻辑单位,是根据作业的不同段进行地址划分的。
2。页的大小固定由系统决定,在硬件结构上,把用户程序的逻辑地址划分为页号和页内地址的俩部分,所以只能由一种大小的页面。而段的长度却不固定,由用户决定。
3,分页的地址空间是一维的,用户程序的地址是单一的线性地址空间。而分段中是二维的,需要给出段名和段地址。

如何理解:
页式,一个程序的各页是根据你的程序空间连续编址的,程序地址空间只有一维;而段式,一个程序拆分成各段,独立编址(各段都从零开始编址),程序地址空间有两维。例如一个50KB的程序,页式分配,不妨设每页4KB,各页地址分别为04,48 … 44~48;而段式分配,各段地址则可能是020,020,0~10

信息共享

分页系统中,每个进程建立页表,每个页表中页表项的页号和物理块号是一样的,所以多个进程访问时,他们访问的代码程序的物理地址空间是一致的,在这基础上建立了自己的数据区,实现共享。
在分段系统中,为不同进程都设置一个段表项,让它的基地址指向共享区。
数据在设立一个段表项

段页式

先将用户程序分成若干个段,再把每个段分成若干个页,并为每一个段赋予一个段名。
段页式系统中,地址结构由段号、段内页号、页内地址三部分组成。
地址变换
系统需要同时配置段表和页表。段表的内容是页表始地址和页表长度.
地址变化
配置一个段表寄存器,其中存放段表始地址和段长。进行地址变换时,首先利用段号S,将它与段长TL进行比较,若S<TL,表示未越界,于是利用段表始地址和段号来求出该段所对应的段表项在段表中的位置,从中得到该段的页表始地址,并利用逻辑地址中的段内页号P来获得对应页的页表项位置,从中读出该页所在的物理块号b,再利用块号b和页内地址来构成物理地址
在段页式系统,为了获得一条指令或数据,须三次访问内存。第一次访问是访问内存中的段表,从中取得页表始址,第二次访问是访问内存中的页表,从中取得该页所在的物理块号,并将该块号与页内地址一起形成指令或数据的物理地址;第三次访问才是真正从第二次访问获得的地址取出指令或数据。

地址变换

在这里插入图片描述

虚拟内存

局部性原理

程序运行存在局部性现象。
俩方面:
1.时间局部性。如果程序中的某条指令被执行,则不久以后该指令可能再次执行;如果某数据被访问过,则不久以后该数据可能再次被访问。产生时间局部性的典型原因是在程序中存在着大量的循环操作
2.空间局部性。一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问,即程序在一段时间内访问的地址可能集中在一定的范围之内。
基于以上,程序在运行之前没有必要全部装入内存,而仅需将当前要运行的少数页面或段先装入内存便可运行

虚拟存储器的基本工作情况

程序在运行时,如果它要访问的页或段已经调入内存,便可以继续执行下去,但如果程序所要访问的页或段没有掉入内存,便发出缺页中断请求,此时OS将利用请求调页或段将他们调入内存,以使进程能够继续执行下去,如果此时内存已满,无法再装入新的页或段,OS还将利用页段置换功能。
虚拟存储器是指具有上述的请求调入和置换功能,能从逻辑上对内存容量加以扩充的一种存储器系统。其逻辑容量由内存容量和外存容量之和决定。
从逻辑上扩充内存。
虚拟存储器采用一下方式之一实现:
分页请求系统:
它允许用户程序只装入少数页面即可启动,以后再通过调页功能及页面置换陆续的吧即将到来运行的程序掉入内存,同时把暂不运行的页面换出到外存上。置换时以页面为单位。
请求分段系统
它允许用户程序只装入少数段的程序和数据即可启动运行。以后通过调段功能和段的置换功能将暂不运行的段调出,再调入即将运行的段。。置换是以段为单位进行的

请求分页存储管理方式

在这里插入图片描述
状态位:指示是否掉入内存
访问字段A:记录本页在一段时间内被访问的次数
修改位M:标示该页在调入内存后是否被修改过。修改后调出必须写入外存
外存地址:用于指出该页在外存上的地址,通常是物理块号,供调入该页时参考。

内存

主存就是内存,内存就是主存。
在物理上是DRAM动态随机存储器。
在逻辑上是一个线性的字节数组,每个字节有唯一的地址。

物理和虚拟寻址

自然的寻址方式是物理寻址。
例如主存的第一个地址为0,cpu访问物理地址0,主存从物理地址0处开始读取数据返回给cpu,cpu把数据放到寄存器中。
现代处理器使用虚拟寻址。
cpu利用虚拟地址来访问,送到内存之前转化为物理地址。这个转化的过程叫地址翻译。

地址空间

地址空间是一个非负整数的有序集合{0,1,2,…}
cpu从一个有N = 2的n次方 个地址的地址空间中生成虚拟地址,这个地址空间是虚拟地址空间。一个系统还有物理地址空间,对应了系统中物理内存的M个字节:{0,1,2,…,M-1}.
地址空间清楚的区分了数据对象和他们的属性(地址)。数据对象有俩套地址空间中的地址,虚拟地址和物理地址。允许每个数据对象有多个独立的地址,每个地址都选自一个不同的地址空间。
我理解的地址空间:
因为进程和进程之间访问的内存其实是一块内存,他们修改数据,如果没有隔离性的话,可能会修改彼此内存区域上的数据,所以需要用地址空间来隔离,确保修改自己地址空间上的数据不会影响到其他进程。或者没到修改数据,从物理地址0到20是进程A,运行程序B,进程B占了15到30,那么A进程的内存就被破坏了。

虚拟内存作为缓存的工具

概念:虚拟内存被组织为一个由存放在磁盘上的N个连续的字节大小的单元组成的数组。每个字节都有一个唯一的虚拟地址,作为数组的索引。磁盘上数组的内容被缓存在主存中,磁盘上的数据被分割成块,作为磁盘和主存之间的传输单元。虚拟内存分割为虚拟页的大小固定的块来处理,物理内存被分割为物理页。任意时刻,虚拟页的集合分为三个不相交的子集:
未分配的、缓存的、未缓存的。
有些虚拟内存已经对应了物理内存地址,只是还没有东西。这是未缓存的。而有些虚拟内存压根就不对应,这是未分配的,最后就是虚拟内存对应了物理地址,而物理地址中也放了东西就是缓存的。

DRAM缓存的组织结构

SRAM表示位于cpu和主存之间的L1、L2和L3高速缓存,并且用术语DRAM缓存来表示虚拟内存系统中的缓存,它在主存中缓存虚拟页。
虚拟内存将主存视为磁盘的缓存,主存和磁盘上会通过数据传输来完成同步。然而,磁盘(特别是机械磁盘)的设计不能快速的读取或者写入一个字节一个字节的数据,因为它的随机读写性能比较差。比如系统要读取一个数组的所有数据,它就要访问数组的所有内存,而如果这些内存不在主存中,就得从磁盘上去装载数据到主存。那么如果是一个字节一个字节的读,可能就要在磁盘和主存之间传输 N 次数据,这样就会导致性能变得很差。

页表

同任何缓存一样,虚拟内存系统必须有某种方法来判定一个虚拟页是否缓存在DRAM中的某个地方。如果是,系统还必须确定这个虚拟页存放在哪个物理页中。如果不命中,找出这个虚拟页在磁盘上的位置,在物理内存中选择一个牺牲页,并将虚拟页从磁盘复制到主存中,替换牺牲页。
这段好难懂,一会虚拟页,一会物理页,一会磁盘,我们先搞清楚这三个东西是啥
物理页,是主存和磁盘交换数据的数据块。也就是说物理页,是主存DRAM中的某个数据页,而虚拟页,就是磁盘上的数据块缓存到主存上后对应的虚拟地址页,cpu通过虚拟地址转换物理地址来访问主存上的数据,这里的物理地址不是磁盘上的地址,而是主存上的地址。(有没有人和我一样一想到物理地址就对应了磁盘,产生了很大误解)。
有一个存放在主存的数据结构叫做“页表”,页表将虚拟页映射到物理页。每次地址翻译硬件将一个虚拟地址转换为物理地址时,都会读取页表。操作系统负责维护表的内容,以及在磁盘与DRAM之间来回传送页。
页表就是一个页表条目PTE数组。虚拟地址空间的每个页在页表中一个固定偏移量处都有有一个PTE,它存放着物理页的地址。

页命中

当cpu想要读虚拟内存中的一个字时,地址翻译硬件将虚拟地址作为一个索引来定位PTE,并从内存中读取它。所以使用PTE中的物理内存地址,构造出了这个字的物理地址。

缺页

DRAM缓存不命中称为缺页。从PTE的有效位判断出没有被缓存到内存中,触发缺页异常。缺页异常调用内核中的缺页异常处理程序,该程序会选择一个牺牲页,如果这个牺牲页已经被修改了,那么就把它复制回磁盘,然后把需要缓存的页从磁盘复制到牺牲页中,无论如何牺牲页都要修改,牺牲页中原有的内容就放回了磁盘,然后更新PTE

缺页中断

分配页面

PTE中,标志为0,未缓存到主存,它放的是磁盘地址,标志为,表示缓存到了主存,放的是内存地址。
比如调用malloc,就是在磁盘上创建空间并更新PTE。

虚拟内存作为内存保护的工具。

提供独立的地址空间使得区分不同进程的私有内存变得很容易。但是,地址翻译机制可以以一种自然的方式扩展到更好的访问控制。
在PTE上增加额外的标志位。SUP、READ、WRITE。
如果违反了标志位的权限,cpu触发保护故障。Linux一般将异常报告为“段错误”.

地址翻译

地址翻译是一个N元素的虚拟地址空间中的元素和一个M元素的物理地址空间中元素之间的映射
cpu有个页表基址寄存器指向当前页表。n位的虚拟地址包含俩个部分:一个p位的虚拟页面偏移和一个n-p位的虚拟页号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值