内存管理与虚拟内存

内存管理与虚拟内存1

先列一下基本概念:

概念介绍
页框内存中固定长度的内存块
固定长度的数据块,储存在外存
变长的数据块,储存在外存中,段内部可以分页
虚拟内存虚拟储存的大小搜计算机系统寻址机制和可用的的备用内存量的限制,而不受内存位置实际数量的限制
虚拟地址虚拟内存分配给某一个位置的地址,它是的该位置可被访问,就好像是内存的一部分
虚拟地址空间分配给进程的虚拟内存
地址空间某进程的内存地址范文
实地址内存中实际的物理地址

内存管理的需求

重定位

程序员不知道哪些进程将会驻留在内存中,而操作系统将会在某些情况下选择调度进程到外存(挂起进程),但是进程换回内存不一定在原来的区域,所以操作系统需要提供一种机制,可以将一个虚拟地址映射到一个真实的物理地址,这就是重定位。

硬件层面如何进行重定位?大致过程如下:

在这里插入图片描述

操作系统通过一个基址寄存器获得进程的地址起点,通过逻辑地址的相对偏移的加法得到具体的物理地址,然后通过一个界限寄存器判断当前是否越界,如果越界就产生中断(实现内存保护与隔离),否则就直接访问。

保护

每个进程都需要被保护,以免被其他进程干扰。内存保护包括两个维度:

  1. 其他进程不能未经授权的访问进程的内存单元
  2. 用户进程不能访问操作系统的任何部分

内存保护需求需要硬件而不是操作系统来满足,因为操作系统不能预测程序可能产生的所有内存访问,即使可以访问,判断是否违法的过程也十分耗时。要判断内存访问是否违法,处理器硬件有这个能力。

共享

允许多个进程访问内存的统一部分,在操作系统中十分有必要,比如当多个进程执行同一个程序的时候,可以让多个进程访问同一个副本,更加节省空间。

逻辑组织

逻辑组织指的是进程在内存中的地址空间的组织形式,例如通过分段或者分页等方式划分为多个逻辑部分,每个部分的大小和权限不同

物理组织

操作系统需要解决以下两个问题:

  1. 供程序和数据使用的内存可能不足,这个时候程序员可能需要使用覆盖 overlaying技术对程序进行物理组织,不同的模块被分配到内存的同一区域,而主程序决定何时换入换出
  2. 多道程序设计环境中,程序员可能不知道还剩多少内存

这就是操作系统的物理组织需要解决的问题。

内存分区

对内存进行逻辑组织。处理器将程序装入到内存中,在没有虚存的情况下也会将进程挂起到外存中,如何进行内存管理,才可以尽量大的提高内存的使用率,并提高程序的运行效率。以下是几种对内存的逻辑划分方式:

固定分区

简单的将内存分为若干固定长度区域。所以有两种分法,一种就是每个分区大小都一样,一种是分区大小不都相等。

如果使用大小相等的内存分区,活动放入任何一个分区都一样,不需要放置算法:

  1. 程序可能太大而不能放到一个分区中,此时,程序员必须使用覆盖技术
  2. 内存的利用率非常低,有些很小的内存占用活动也会占用固定大小的内存大小

如果使用大小不等的内存分区,那么需要考虑放置算法,同时:

  1. 分区的数量在系统生成阶段已经确定,限制了系统中活动进程的数量。
  2. 较小的活动无法很好的利用分区空间,如果一个进程占用了跟它最适配的内存分区,它只能去更大的内存分区,造成内部碎片

所以基本不适用固定分区,他会造成大量内部碎片,也让操作系统变得不那么灵活了

动态分区

那如果不固定分区呢,换句话说,分区长度和数量都可变,进程装入内存时,系统分配给它它需要的内存空间,看似非常合适,实际上动态分区会造成大量的外部碎片, 因为进程的换入和换出的时机并不确定,进程的换出会造成内存出现大量空洞,如果这些空洞无法被后来的进程完美填充,将造成越来越多的内存碎片。

有一种成为压缩(compaction)的技术,操作系统通过不时移动进程,是的进程占用的空间连续,消除外部碎片。但是,这是一个非常耗时的过程,而且对此操作系统的重定位能力提出了新的要求:动态重定位,也就是在换内存地址后,程序依然能确保内存的访问和保护。

还有一种补救是设计更好的算法,让新来的进程能更完美的填充那些空洞,可以考虑的放置算法有三种:

  1. 最佳适配。选择大小最接近的块
  2. 首次适配。从头扫描,选择第一个大小足够的块
  3. 下次适配。从上次放置的位置开始扫描,选择第一个大小足够的块

可能存在一些方法可以尽量消除动态分区造成的外部碎片,但是这肯定是一个消耗时间的过程,因此动态分区也被淘汰了

伙伴系统

在这里插入图片描述

集合固定分区和动态分区的优点。考虑将内存大小分为一个2k大小,可以为这个内存大小建立一个二叉树进行管理。具体的操作过程如下:

  1. 子节点代表的大小为父节点的一半。
  2. 叶节点可以被分配,通过二分延伸二叉树,直到当前叶节点最适合当前申请内存,此时,标记这个叶节点为被分配。比如一个进程申请100KB,内存中有一个1024KB的叶子节点,那么它将分两次,分到128KB,然后将一个叶子节点分配给这个内存
  3. 如果一个资源被释放,它的叶节点将会被收回,此时二叉树从此开始不断合并未分配的叶节点,直到根节点或者有叶节点被分配无法合并,比如释放一个128KB的内存,将不断合并如果合并到1024KB,发现此节点的兄弟几点被占用,停止合并

伙伴系统克服了固定分区和动态分区的缺陷,但是依旧被更先进的分页分段机制替代。但是伙伴系统在并行系统中有很多引用,他是未并行程序分配和释放内存的一种有效的方法。

分页与分段

分页即将内存分为大小相等的小块,称为页框,同时把进程也分为相同大小的小块,成为,维护一个页表,将每个页都对应到一个页框上。这样内存的内部碎片仅仅是最后一页的小部分,并且没有外部碎片,实现了内存的的高效利用。

  • 在任何时刻,操作系统都维护空闲页框的列表,如果一个进程要载入内存,操作系统将在页框中选择若干页框,为进程建立一个页表,然后载入进程。
  • 如果没有足够的连续页框保存进程,仅仅是页表中的页框号不连续而已,只要现在剩的页框够,进程都可以载入内存
  • 页和页框的大小被规定为2的幂,这是因为可以方便的将一个二进制地址分为页号和偏移量
  • 地址的重定位过程即分离出逻辑地址中的页号,对应到页表中找到页框号,再通过逻辑地址剩下的部分得到偏移量,将页框号和偏移量拼在一起就是物理地址

分段类似于分页,但是不产生内部碎片产生外部碎片,同时将对程序员可见以便程序员更好的组织程序和数据。但是分段依然有最大长度限制,逻辑地址和物理地址也不是见到那的对应关系,因为段长度不一样,段表项还需要确定段的长度以确保不越界访问。

优缺点:分页空间利用率比较高,也能更好的实现保护和共享。分段易于动态拓展,处理不断增长的数据结构比较擅长,也提供给程序员对程序和数据的管理手段(比如可以单独规定某一段的保护和共享)。


虚拟内存

硬件和控制结构

虚拟内存建立在分页和分段技术的基础上,主要体现在以下的两点:

  1. 进程访问的地址都是逻辑地址,通过动态的转换变成物理地址再访问,这意味着一个进程可以被换入和换出内存,进程可以在执行过程中的不同时刻占用不用位置的内存
  2. 一个进程可以被划分为多个块(页和段),这样一个进程中的某块可能不需要在内存中,同时进程的地址空间可能不连续。

进程只能在内存上运行,但是虚拟内存技术可以让用户感到有更大的内存,且通常分配在外存上,这会带来两个效果:

  1. 可以在内存中保留更多的进程,因为可以只装如进程的某些块
  2. 可以运行比内存都大的更大的程序,程序大小不再受内存限制

局部性原理

虚拟内存仅仅载入进程的一小部分会马上执行的部分,如果操作系统需要使用这个程序的其他部分,需要产生一个Page Fault,操作系统阻塞进程,通知换入内存,然后继续执行进程。因此,任何时刻,任何一个进程都只有一部分位于内存中,因此可以在内存中保留更多的进程,可以更加节省挂起进程的时间。但是,如果操作系统几乎所有的内存空间都被占用,那么就需要换入需要的程序,如果被换出的内存块正好马上要被使用,它又要马上被换入,这时称操作系统发生了系统抖动。操作系统应该尽量避免系统抖动,那能避免抖动的原理就是局部性原理

虚存的现实性和可行性来自于局部性原理,简单来说,局部性原理指的是一个进程中的程序和数据的访问的集簇倾向,时间局部性是指一个数据项或指令在一段时间内被反复使用的特点,空间局部性是指一个数据项或指令在一段时间内与其相邻的数据项或指令被反复使用的特点。

分页

分段和分页的区别:

  1. 页的大小是固定的,由操作系统决定,通常为 2 的幂次方。而段的大小不固定,取决于我们当前运行的程序
  2. 页更多是物理方面的分割,将内存分为等大的小块。而段更多是逻辑上的分割,将程序分割为多个段
  3. 分页出现内部碎片而分段出现外部碎片
  4. 页表项和段表项不同
  5. 分页机制对程序员透明。分段机制需要程序员显式的制定程序的段

分页虚拟内存的寻址过程如下,考虑使用TLB和高速缓存。

在这里插入图片描述

页表项和段表项

一个页表项包含以下内容:

  1. 存在位。标识此页是否在内存
  2. 修改位。标识此页在上次换入后是否修改,这样操作系统可以在换出的时候考虑是否更新外存
  3. 其他控制位
  4. 页框号

页表项中没有页号,因为使用了直接映射,页号就是页表项的索引

段表项包含以下内容:

  1. 存在位。标识此页是否在内存
  2. 修改位。标识此页在上次换入后是否修改,这样操作系统可以在换出的时候考虑是否更新外存
  3. 其他控制位
  4. 段长度。段的长度不定,需要在此规定
  5. 段基址。段开始的地址
页表结构
  • 大多数操作系统中,每个进程都有自己的页表
  • 可能存在巨大的程序占用巨量的虚拟内存空间,此时它的页表将变得很大,为了克服这个问题,大多数系统将页表也放到虚拟内存中服从分页管理,也就是说,页表也跟进程一样,一部分在内存,一部分在外存,如果页表的某部分在内存中找不到,也需要操作系统进行换入操作。
  • 为了解决可能的大页表问题,可以进行页表的分级管理。同个将页表号分级,根页表找到次页表,次页表继续找,最终得到页框号。这样页表就可以储存在外存中,如果根据根页表找到的次页表不在内存,将其换入即可。

在这里插入图片描述

倒排页表

倒排页表的大小固定,不需要为每个进程都维护一个页表。那么它如何寻址?

  1. 通过进程的PID和页号,经过散列函数的计算,将得到一个页表项,如果哈希冲突,将通过一个链指针指向下一个项,然后通过对比进程标识符得到最终的页表项,找到对应的页框,如果找不到,说明不在内存中。
  2. 倒排页表的大小由内存大小决定,内存中的每个页框都在页表中存在,如果页表中找不到,代表此时出现了Page Fault
TLB(转换检测缓冲区,快表)

按照原设计,操作系统每次访问数据都至少需要访问两次内存,一次去页表项,一次去数据。通过使用TLB加速这一过程 。操作系统为页表项使用一个特殊的高速缓存。

如果考虑了TLB和Cache,每次操作系统先访问TLB找页框号,没找到去页表找,如果找到了就更新TLB,看看高速缓存Cache有没有数据(为了避免多次访问内存耗时),没有就再访问内存;如果没找到就Page Fault阻塞进程,换入内存,继续执行进程。

页表一般使用直接映射,即页号就是页表项的索引,而TLB一般使用关联映射,即需要储存页号和页框号,然后依次对比找页号。

页尺寸

页尺寸不能太大,也不能太小,考虑将页尺寸设计的更下,那么更小的页尺寸可以减少内部碎片,提高内存利用率,但是会让页表变得更大,页表如果更大,一次内存访问更有可能造成两次Page Fault(页表一次,数据一次)。而也尺寸更大这相反,因此设计页尺寸需要综合考虑。

也可以使用可变页尺寸,即设定某些连续的空间使用更大的页尺寸比如指令和数据,而一些较小的连续空间比如栈使用更小的页尺寸。但是一般不用,它太复杂了,页的尺寸会影响操作系统的许多特征,可变的页尺寸将会让操作系统变得极为复杂,

段页式

段页式虚拟内存结合了分页和分段,先将程序分段,再将每段分页,大概的寻址过程如下:

在这里插入图片描述

置换策略

当发生了Page Fault时,操作系统需要将外存中的某些块换入,如果内存中尚有空间就直接换入,如果没有,就需要选择一块,将其换出,即页面置换。常见的选择策略如下:

  1. 最佳页面置换算法(OPT,Optimal) :理论上最优的算法,如果能换出以后都不会用的,自然是最好的,但是操作系统怎么能预测未来呢。这个算法一般作为理论参考。
  2. 先进先出页面置换算法(FIFO,First In First Out) : 简单高效的算法,维护一个队列就可以实现。但是FIFO忽略了页的使用频率而只看进入内存的顺序,反而可能造成系统低效。
  3. 最近最久未使用页面置换算法(LRU ,Least Recently Used) :记录每个页的访问时间,当需要换出的时候,找到最久没有使用的换出。理论上来说,长久没有使用的块在未来也大概率不会使用了。
  4. 最少使用页面置换算法(LFU,Least Frequently Used) : 类似于LRU,但是看的是使用频率小而不是使用时间早。
  5. 时钟策略(Clock):LRU的简洁版,试图以更小的代价实现LRU。每个页框都有1和0两个标记,当页框被载入和被访问时都会被置为1,当需要找到一个换出页框时,从上次停留的位置开始循环扫描页框,当页框标记是1,将其置为0继续遍历,当页框标记是0,换出,将指针指向下一个页框。有点像FIFO,但是跳过了那些最近用过的页框,而如果一个页框被扫过标记变为1,视为最近没用过的页框下次扫到将被换出。

  1. Curry Arthur 2023/04/21 ↩︎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值