• 操作系统------内存管理(2)非连续分配内存 段页式管理


    产生背景:不管是固定分区还是动态分区,都会有一个现象级影响,内存利用率不高。固定分区会产生较大的内部碎片,而动态分区会产生很多的外部碎片(内存被一直分区,导致有很多分区,若有一个大一点的进程进入内存,是进不来的),这些内存碎片都利用不起来。


    非连续内存分配

    定义:进程运行时在内存中的地址空间可以是离散的,一块一块的。

        


    1-1 基本分页存储管理方式

              1-1-1 什么是页

     页就是内存分配的基本单元。

    整个内存按照固定大小去分区,每个分区就是一个页。

    说白了就是固定分区。一般为4K。

    没有了外部碎片,即使有内部碎片,但是很小,可以接受。

              1-1-2 什么是页表(慢表)

    进程中的是逻辑地址,而内存中的是物理地址。

    页实现了物理地址的分配,接下来我们要将逻辑地址分配,从而更好地关联,映射起来。

    所以,逻辑地址地分页地大小也是4K,即和物理地址的页相同。

    利用页表来记录此进程分了多少页,然后在和物理地址的页对应上。

    页表是一种数据结构,存放在进程PCB中。

    页表是一个一维数组,因为页号和数组下标索引刚好对应上。

    页表不能太大,会降低内存利用率。

    页表归根结底也是在内存中,准确地来说是在PCB中,那么CPU也需要一个组件来告诉它页表在哪里。由于就有了页表寄存器,它不存储页表,只存储页表地起始地址和页表长度。

     

              1-1-3 地址变换机构

    页表实现了逻辑地址和物理地址的映射关系,但这还远远不够,需要地址变换机构得到真正的物理地址(即那一串二进制数字),此动作非常频繁,需要足够快的速度,所以交给硬件去完成。

    每次访问内存都需要进行地址转换。

          

            A % 4K = A & (4K-1)

              1-1-3 快表(缓冲思想)

    根据页号找到块号,即访问页表,是一次访存。计算出物理地址后,还要去进行数据访存。光要读取这个数据,我就已经访问了两次内存了。性能不太好。

    可以将页表放入到高速缓存中。

    流程即:当一个进程要对一个数据进行操作时,不去内存中的慢表去看,而是先去高速缓存中的快表去看,如果匹配成功,那么进行访存。 <-------->  一次访存。

    若快表中没有,那么回慢表中找,同时将此条记录同步到快表。(局部性原理)

    但是你这样有点多此一举,相当于访问了两次页表,所以OS有一个优化的动作,会让访问快表和访问慢表并行,看看快表是否命中。

    快表是二维表,因为它的页号不连续。

     

              1-1-4 两级页表(索引思想)

    聊聊为什么会有两级页表甚至是多级页表,我们以32位机为例。

    一个页表最多占多少内存取决于我们存储多少个页号。在逻辑地址中前20为用作页号。

    2的20次方就是1024×1024,然后在×4个字节,所以每个页表最大为4MB,这个大页表放在内存中显示很不好,太大了,占用了大量的连续空间,而且程序是动态装入的,我一段时间只需要访问某一部分页表,没必要把整个页表加载进来。而一个一个页表所映射的内存大小为 1024×1024×4K ,即4GB。

    所以就产生了多级页表,我按照1024个页号进行划分,存入内存中刚好就是4KB,而且二级页表也是4KB,与我的页框大小完美吻合,这可能就是设计者的初衷。这样我的二级页表是实现了离散存储,建立了一个索引目录进行管理。

    比如,我要取数据。在页表寄存器中找到了一级页表的地址,然后进行位运算得到一级页号,然后得到二级页表的存放位置,然后在进行位运算得到实际地址的块号,然后在加上偏移地址就找到了。

    下图为逻辑地址表


     

     

     


            1-2 基本分段存储管理方式

                1-2-1 什么是分段

    将用户进程进行段式管理,因为每一个都是4K,页太多了,不利于管理。而且用户进程是模块化的,不一定就是4K。还是一句话,按照需求,按照模块化进行分段。

    编译器帮我们分段。

    段表是二维空间。

    段表的起始地址和长度在寄存器中,即段表寄存器。实际的数据放在内存中。


     

            1-3 段页式管理方式

    将用户进程进行逻辑分段,将内存进行物理分页。

    首先从段表寄存器中得到段表的起始位置,即去内存中寻找,利用位运算得到段号,然后得到相应的页表和长度。这里有一个对应关系,一个段表项即一个模块,对应着至少一个页框,所以一个段表项对应着一个页表,整个页表你需要段表项的块号去找,得到页表后,利用位运算得到页号,然后再得到了块号,然后与偏移地址结合得到物理地址。

     

     

     

     

  • 相关阅读:
    第5章 网络编程
    微服务从代码到k8s部署应有尽有系列(七、支付服务)
    Java语法小知识+数据结构常见选择题型
    浏览器中的页面循环系统(二)Webapi:setTimeout是怎么实现的
    数据库与数据库管理系统 MySQL的安装 SQL语言学习:DDL、DML
    【FFMPEG】Windows下将ffmpeg编译成lib和dll完整教程
    辅助驾驶功能开发-功能规范篇(22)-2-L2级辅助驾驶方案功能规范
    仿真与烧录程序有哪几种方式?(包含常用工具与使用方式)
    MATLAB基础应用精讲-【基础知识篇】MATLAB程序优化-通过tic函数和toc函数进行程序运行分析
    Linux环境下安装docker环境(亲测无坑)
  • 原文地址:https://blog.csdn.net/weixin_51676493/article/details/126201734