首页 > 编程学习 > 面向面经学习之操作系统 第二章 内存管理 (第一节 分页式管理)

一、虚拟内存和分页式内存管理

1、分页式内存管理的基础:

        把进程的相对地址空间,或者说逻辑地址空间,等分成若干个大小相等的块,称为页,页的大小一般不大4k,2k或者1k。

        那么页的大小决定了我们将来内存分配的力度,在真正的物理地址空间中,我们也要把空间划分成大小相等的页帧。页帧和页的大小必须完全一样。这样划分后,我们可以使用一个叫做页表的管理结构。

        页表里面记录的是页号和页帧号的对应关系,我们把页装入到页帧中来实现地址分配。这样我们就无需把页连续地存入物理地址空间中。我们只需要把n个页装入n个页帧中。

        上图为示意图,但实际使用中,页表里不存页号,页号就像数组下标,下标就是页号,所以不需要存。

        我们在申请使用内存时,没有必要把全部的页装入内存,我们只需要把当前正在使用的页面装进来。

        但这也会产生一个问题就是“抖动”,可能会在装入新页的时候把不那么重要但依然要使用的旧页给换出了(即内存频繁地输入输出)。1是磁盘读写速度很慢,这样会严重影响性能,2是CPU进行这样额外的多于操作,是很没有意义的开销。

2、虚拟内存:

        

虚拟内存提供了三个重要的能力: 缓存内存管理内存保护

1. 将主存视为一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据

2. 为每个进程提供了一致的地址空间,简化内存管理

3. 保护了每个进程的地址空间不被其他进程破坏

二、页表与地址重定位

        

1、观察一个页有多大。这里为 4K  = 2 的 12 次方,所以逻辑地址的低 12 位 就是页内偏移量,剩余的为页号(即下标)。从而将逻辑地址切分为两段,页号和页内偏移

2、查页表下标和页号相等的位置,然后看标志位:Present/absent bit  如果该页在内存中,标志为1,反之为0.

3、接着来看页帧号, 这个页帧号 为 110, 把页帧号放在物理地址的高段,把页内偏移直接拼接在物理地址的地段,从而获得物理地址。

(如果是十进制,可以简单地:逻辑地址除以页的大小,商是页号,余数为页内偏移。查表,然后,页帧号乘以页的大小,再加上页内偏移得到物理地址。)

页表单元结构:

1、Present/absent:是否在内存中。

2、Referenced 近期被引用过 置 1 ,反之置 0

3、Modified(脏位): 页面当中的数据在内存中被修改过置 1, 反之置零。如果页面当中的数据在内存中没被修改过,那么在置换出去的时候可以不用保留数据下来。

4、Protection: 读、写、执行、什么样的人有权限balabala......

三、TLB、多级页表和倒排页表

1、如何加速页表访问:

      页表到底有多大?

        比如,逻辑地址 32 位,一个页大小 4k:

        一个页 4k = 2^12 ,偏移量为 12 位, 32 位的逻辑地址, 那么页号有 20 位,从而要有 2^20 个页表项。也就是 1M 个页表项。1个页表项是 4Bytes, 那么一个页表就有 4MB 这么大。

        4MB 的页表我们该放在哪里呢?肯定不能在寄存器中。一般放在内存里,而内存访问速度相比寄存器很慢,所以我们需要加速。

        所以我们把最常用的页表项放在高速缓存内,这个数据结构叫做 TLB。

        TLB 叫快表,原始页表叫慢表。快表中能找到,叫做命中,去慢表查叫未命中。我们要求命中率要到 80% 以上。

        一般一个进程给 16 个快表项。

2、大页表怎么拆成小页表:

         1M 个页表项也就是 100w 个页表项我们都要用到吗?其实并不是。根据上面提到的虚拟内存的使用,虚拟内存是操作系统许诺给进程的一个非常大的地址空间,我们可以用到 2^32 个地址空间,高达 4 个 G。 但实际上并不是这样,我们真正的大部分进程只需要用到几M或几十M的地址空间就够了,其他的地址空间是空闲的。

        对应到页表上,就是 1百万个页表项所对应的1百万个页,其中可能真正用到的只有几千个,或者上万个就差不多了,剩下百分之九十九的页都是空的。页是空的,页表项就是空的。页表项是空的,在内存里就存了一堆没有用的数据,所以我们考虑把页表项分级。从而我们可以把页表拆成若干个小页表。

        比如我们有 一百万项的大页表,我们把它拆成 1024个小页表。每个小页表包含 1024 项,我们再用一个页目录表,记录这1024 个小页表是否使用。我们刚说过,我们真正有用的只有几千个页,也就是小页表大概只会使用几张。看上图这个例子,我们拆完后这个进程只有不到三千个页面是真正放内容的,那么我们使用3张小页表,可以映射3072个小页面。我们只需要使用这三张小页表就可以记录这3072个页面所对应的页帧和他的一些标志位。再加上这个页目录项表,我们只使用了4张小页表,就完整地记录了这个进程使用的页面的情况。

      我们以什么标准进行拆分的呢?

        目标:把每一个小页表都能装到一个页中。

        一个页面是 4k, 一个页表项 4个字节, 从而 4k/4 = 1024 , 一个小页表里面最多容纳 1024 个页表项。 1024 = 2^10, 体现在页号里面就是最多每段页号是 10 位, 32位地址空间,低12位页内偏移,高10位是页目录项,中间10位是小页号。

3、如何装下更大的页表:

      64位系统怎么拆分?倒排页表(转置页表)

        我们目前的实际情况:操作系统64位,物理地址是64位,但实际上我们可能装入的物理设备只有4G、8G或者16G。服务器上也就是几百G。

        所以我们以真实内存作为页表项的索引,记录的是每一块真实内存物理的页帧对应的是哪个进程的哪一页。(原本我们是记录的每个进程里的页对应的哪个页帧。)因为页帧数有限,所以这个页表就小得多:真实内存4G的话我们只需要表达1M个页表项。

        倒排页表操作系统中只需要有一张,和真实内存大小一致即可。

        现在物理地址是下标,逻辑地址是内容。我们按照页号进行哈希散列,冲突排队列。比如我们按地址的低多少位进行哈希


本文链接:https://www.ngui.cc/el/1461183.html
Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000