清华大学操作系统课程笔记:计算机体系结构和内存层次

本文已收录于 清华大学操作系统课程笔记 系列,共计 9 篇,本篇是第 2 篇

计算机体系结构和内存层次

存数据的地方:CPU里的寄存器、内存、外存。

32位机器也就是可以一次性从内存中读写32位(4字节)数据

详情查询:

内存层次

通过MMU(Memory Management Unit,内存管理单元)来作为虚拟(逻辑)地址和物理地址之间的枢纽。

  • 抽象:逻辑地址空间
  • 保护:每个进程只能访问自己的地址空间。
  • 共享:访问相同内存
  • 虚拟化:每个进程的地址空间编号都是一样的,分配一模一样的地址空间。甚至可以大于物理内存

操作系统内存管理方式

  • 重定位:每个地址用一个段地址+偏移得到的。这种对特定机器才有用,不灵活。
  • 分段:我们希望一个进程占用的内存空间不一定非要连续。代码段、数据段、堆栈分离。至少分成三块。不过这要求段里的内存空间是连续的,要求还是有点高。
  • 分页将内存分为基本单位。基本单位是连续的。方便后面的页调度,置换。
  • 虚拟存储:希望把数据存在硬盘上,目前多数操作系统(例如Linux)使用的方案

地址空间&地址生成

地址空间的定义

首先是物理地址空间:是由地址总线的条数决定的

逻辑地址空间是CPU运行的进程所看到的地址

一个是内存的角度。一个是CPU的角度。

地址生成过程

https://www.bilibili.com/video/BV1xJ411W71v?p=23 11分

Ps:由CPU硬件去实现硬件转换(MMU)——后面要讲的页表功能。转换的表(页表)是由操作系统建立的。

地址检查

连续内存分配

内存碎片(含外碎片和内碎片)

碎片分为两种,外碎片是两块之间的;内碎片是分配给进程区域内没法利用的区域。

外碎片:两块之间小的空闲块。

内碎片:比如说程序需要510字节,但分配内存只能以2的整数幂的形式分配512字节。多出来的2字节就是内部碎片。

动态分区分配

大小可变,地址连续。

操作系统需要做的事是维护一个已分配分区的数据结构,还要知道空闲分区的大小位置等信息。

对于找分区的不同,有以下策略。动态分区的分区策略(排序算法不同):

  • 最先匹配
  • 最佳匹配
  • 最差匹配(由大到小,第一个就是)

最先匹配(first fit)——碰着那个是哪个

first fit 内存分配算法:

最佳匹配(best fit)——找个最好的位置,大小合适

最差匹配——找最大的空闲分区

碎片整理

碎片紧凑

我们想把他们压缩在一起,这样可以腾出更多连续的区域供分配。但不是你想动就能动的。必须所有进程都支持动态重定位。不允许正在运行的时候搬动,绝对地址程序也不可以。关于具体的做法再议。

问:什么时候可以搬动?

答:进程处于等待状态的时候才可以搬动。

关于开销问题也要考虑不是任意时候想怎么搬动就怎么搬动,要考虑综合的开销。

分区对换(早期内存紧张的时候)

第二种做法是分区对换

https://www.bilibili.com/video/BV1xJ411W71v?p=25 第4分钟

思路:

把处于等待状态的P1放在外存中:

在Linux中swap早期就是为了扩展内存用的。早期内存很紧张。把处于等待状态的进程移动到外存中。

连续内存分配实例:伙伴系统

第一维是空闲块的大小,从小到大排成第一维。

参考信息:

我们在实现的时候,就实现这两个函数alloc 和 free就行了。

非连续内存分配

改进:连续内存分配很麻烦,例如有时候用户想要一块内存,但内存中恰好没有连续的一块内存给他分配。

其中段式分配的块比较大,页式分配的块比较小。段页式是将段式和页式结合起来的方法(十分重要)

非连续内存分配的目标是提高利用效率。

eg:例如共享函数库

Ps:简单来说段式存储分配的比较大,以段为基本单位。页则更小,分配的时候以页为单位

段式存储管理(以段为单位分配)

段地址空间

一般来说也很少有跨段访问的情形。

这样在物理空间中就可以不连续了:

段访问机制

逻辑地址由二元组由段号s和段内偏移地址addr表示:

访问的具体过程可以参考视频:https://www.bilibili.com/video/BV1NE411R7dp?t=251.1&p=36

页式存储管理(分成更小的块,以页为单位)

页式存储管理的概念

在32位机器中,4k,4096B是常见的页帧大小。页帧用来描述物理页面,页面用来描述逻辑页面。

逻辑地址到物理地址的转换

  • 页表:用于保存转换关系
  • MMU(存储管理单元)/TLB(快表):让地址转换快速的进行

下图S是帧的位数:

举个例子:不管是逻辑地址空间还是物理地址空间计算方法一样

物理地址空间的划分:

逻辑地址空间的划分:

页表

具体查询过程可以看视频:https://www.bilibili.com/video/BV1NE411R7dp?t=387.6&p=37

f左移s位,加上偏移o。

页表负责逻辑页号到物理帧号之间的转换:

页表结构:

修改位:对应的页面中的内容是否修改了。

引用位:在过去一段时间,是否对他有引用,是否访问过。

实例:https://www.bilibili.com/video/BV1NE411R7dp?t=179.3&p=38

性能问题:需要两次访问,获取页表项和访问数据;内存很大的话,页表也非常大。

如何解决?

  • 缓存:快表
  • 间接访问:切分成子表(多级页表)

快表和多级页表

快表,CPU里面有个关联存储器(TLB)。可以同时的查询多个关联项。虽然在CPU里查找比内存中快得多,但是CPU里的这个快表不能做的太大。

多级页表:通过间接引用将页号分为若干级。上图形成页表树。

查询方式:p1作为第一级页表的偏移找到二级页表的地址;p2作为二级页表项的偏移找到三级页表的地址;从三级页表找到物理内存地址。

Ps:突然想到了数据库里的B+树

可以有效减小页表长度。可以类比查询算法,二叉查找树之类的。

举个例子:

逻辑地址的低10位作为偏移,中间的5位作为第二级页表p2(第二级页表号),高5位作为第一级页表的p1;intel处理器有CR3寄存器,它保存着第一级页表的起始位置。第一级页表的页表项作为第一级页表的起始位置,再加上p2算出来f。

反置页表和页寄存器

提出反置页表的原来是多级页表在大地址空间系统中表现得很繁琐。

针对上面的繁琐问题,页寄存器和反置页表是两个类似的做法。——让页表和物理空间的大小对应起来,而不是逻辑空间。因为逻辑空间的大小大啊

页寄存器的实现

页寄存器中的地址转换

反置页表

Ps:如果vpn不同就表示有冲突,那么就找next。Index就是页帧号。

段页式存储管理(重要)

段式+页式

IMG_256

,所以我们最好将段式和页式结合。

段页式存储管理例子

段页式存储管理中的内存共享

 

作者: 高志远

高志远,24岁,男生

发表评论

邮箱地址不会被公开。