《现代操作系统》阅读笔记——内存管理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winter_wu_1998/article/details/84102399
  • 地址重定位

    • 最开始的计算机没有重定位,程序直接使用内存的物理地址
      • 任然被微波炉,洗衣机等嵌入式设备使用
      • 缺点是一次只能执行一个程序,因为第二个程序地址起始位置会变动
    • 静态重定位
      • 为了解决只能运行一个程序的问题,提出了静态重定位的方法,在每次程序载入内存时,在为每个地址加上程序起始地址
      • 不可被多个程序共享,因为每个程序的其实地址不同,计算出来的绝对地址也不同
    • 动态重定位
      • 不再是程序载入内存时重定向,而是运行时才执行
      • 由基址寄存器和界限寄存器实现
      • 优点:
        • 程序装入内存后可以变动位置
        • 不需要连续的内存,可以分开放,只要每个内存段都有一个基地址(存在每个进程的基地址寄存器中)即可
        • 程序可以被多个进程共享,只要每个进程有相对的基地址寄存器就可以
      • 缺点:
        • 每次读取内存都要经过加法操作,速度减慢
  • 空闲内存管理

    • 首次适配法
    • 下次适配法
    • 最佳适配法
      • 因为会产生大量无用的小内存碎片,性能反而比上面两个差
    • 快速适配法
      • 维护多个链表
      • 速度最快
  • 虚拟内存

    • 当你打开很多进程的时候,你实际使用的内存总量可能已经超过了物理内存的大小,实现这一功能的手段就是虚拟内存
    • 基本思想:将虚拟地址与物理地址映射,以页为单位从磁盘换进换出
    • 虚拟地址通过MMU(内存管理单元)转换为物理地址
    • 只有用到的页需要读到内存中,剩余的内存可以放在磁盘上,通过缺页中断调入内存
    • 这一概念可以让本来的I/O过程变成内存的读写
      • 从文件读取数据可以不通过I/O中断,而是把文件作为内存看待
      • 这便是内存映射的概念,具体可见我CMU 15213 第九章的文章
  • 页表

    • 记录了该进程所有页面的对应的物理内存页号,以及其他信息
    • 页表可以存入专门的页表寄存器,这样在映射时不用再访问内存
    • 也可以保留在内存中,但是每次访问一个地址都要进行多次内存访问
    • 使用多级页表可以忽略未被使用的虚拟内存,减少页表大小
    • 也可以使用倒排页表,使用实际内存而不是虚拟内存的页作为表项,虚拟内存的页为每一项中含有的内容
  • 页面大小

    • 太大经常会浪费页面中被分配的内存,造成内部碎片
    • 大页面能够充分利用TLB空间
    • 太小则页面过多,页表过大,而且一次传输一个页表,太小则传输效率不高
  • TLB加速分页

    • TLB能将最近常用的虚拟地址直接映射到物理内存
    • 由于不用遍历MMU以及求和,TLB比MMU快很多
  • 页面置换算法

    • 先进先出算法

      • 可能会替换掉一些最老但是经常使用的页面
    • 第二次机会算法

      • FIFO的改进算法,如果最老的页面被访问过(访问位R为1),则当做最新的页面加入页面链表
    • 时钟算法

      • 为了避免在链表中移动页面,将链表编程环,指针指向最老的页面
    • LRU(最近最少使用)算法

      扫描二维码关注公众号,回复: 4195595 查看本文章
      • 记录最近每个页面被访问的次数,替换掉最少的页
      • 缺点是会一直记住所有页,于是页面越老越有优势
      • 解决方法:老化算法
        在这里插入图片描述
    • 工作集时钟算法
      在这里插入图片描述

  • 分配策略

    • 局部分配
      • 替换算法值作用于本进程
    • 全局分配
      • 替换算法作用于所有进程
      • 要考虑如何给大小不一的进程分配页面
  • 颠簸(trash)

  • 当所有进程的工作集超过了实际物理内存大小,就可能发生颠簸,即部分页面不停被环进环出
    在这里插入图片描述

在这里插入图片描述

  • 共享页面
    • 当不同用户同时使用同一程序时,程序中的部分(如程序代码)可以被各个进程共享
    • 但是共享代码不可被更改,更改是可以使用写时复制策略,具体可见我CMU 15213第九章的文章
    • 共享库
      • 进一步利用这个概念便有了共享库,不用每个程序单独写一遍库代码了
      • 当共享库被修改时,程序本身不用重新编译,旧的二进制文件任然可用
      • 这一特性对于商业软件很重要,因为源代码是不开源的。当库更新时,用户只需要下载新版本的共享库即可继续运行
      • 由于库是共享的,所以装载时不可使用重定位,因为使用同一个库的程序内存地址不同
        • 使用相对地址代替绝对地址
        • 被称为位置无关代码
  • 锁定页面
    • 包含I/O缓冲区的页面可能会被置换算法选中而换出内存
    • 为了防止这种错误,可以锁住I/O缓冲区的页面
  • 分段
    • 虚拟内存要预先留一些空间给可增长的内存,但是当一个增长的部分到达了预留的最大空间时,可能别的预留空间还很空,于是造成了浪费
    • 解决方案是把程序分为独立的一个个段,各个段相对独立
      • 其实之前虚拟内存也是一段一段的,要理解不同之处在于过去段的起始点是相对于虚拟内存时固定的,所以有些段可能没满,但是分段之后只要所有段内存加起来不超过给虚拟内存的最大内存即可,相当于每个段用链表连起来
    • 每个段可以由单独的权限(比如程序段只能执行,数据段只能读写)
    • 每个段一般只有同一类内容,有单独的基址,至此需要重新编译的部分又缩小了(回忆刚才的共享库)
      在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/winter_wu_1998/article/details/84102399
今日推荐