哈工大李治军老师操作系统笔记【23】:内存换出(Learning OS Concepts By Coding Them !)

30 篇文章 22 订阅

0 回顾

  • 有换入就应该有换出
  • 从get_free_page来
  • 换入和换出应该合着一起工作

1 换出

  • get_free_page()是换入的时候得到一个物理空闲页
  • 并不是总有新的空闲页,因为内存是有限的
  • 所以必须要选择一个页换出去,这一部分主要讲的是算法
  • 这个算法实现的功能就是:
  • 把哪一页从内存当中换到磁盘上,从店面中把哪个商品放到仓库中,腾出地方来,放入别的商品,腾出内存来,换入别的页,所以需要选择一页淘汰,换出到磁盘,应该选择哪一页?
  • 这个算法放哪里?放在get_free_page(),那么,这个出现在哪里?出现在页面中断处理程序,do_no_page里面,就是14号中断的处理程序当中
  • 那里做啥事呢?首先申请一个空闲页,然后从磁盘上读入,那么现在申请空闲页的时候,那肯定有个方法,计算一下是不是空闲页不够了,如果不够了,要找一页换出去然后再申请,所以这部分代码就应该放到这里

1.1 get_free_page()

  • 缺页中断处理程序中,在从磁盘读入数据之前,首先要通过调用get_free_page()在物理内存中分配页
    • get_free_page()并不能总是获得新的页,内存是有限的
    • 需要选择一页淘汰,置换算法
      • FIFO
      • MIN
      • LRU,重点(LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰)

在这里插入图片描述


1.2 FIFO

  • FIFO
  • 使用缺页次数来评价置换算法
  • 下例使用FIFO的缺页次数是7(每次缺页都是要去磁盘读写的)

在这里插入图片描述


1.3 MIN

  • 选最远将使用的页淘汰,是最优方案
  • 还是上方的序列,D要换入,但是C距离最远,所以选C换出再D换入
  • 但这种算法基本不可能实现,因为无法预测哪一页最晚使用
  • 这是个理想算法,操作系统做不到,但可以近似想这个最优来靠近
  • 下例使用MIN的缺页次数是5

在这里插入图片描述


1.4 LRU

  • LRU
  • 用过去的历史预测将来
  • 局部性原理(正是有了局部性,才可以换入换出)
  • LRU是公认的很好的页置换算法
  • 我记得有一个算法很容易和LRU搞混,是哪个?
  • 下例使用LRU的缺页次数是5,达到了和MIN一样的效果

用过去的历史预测将来,来达到近似MIN
LRU算法:选最近最长一段时间没有使用的页淘汰(最近最少使用)


在这里插入图片描述


1.5 LRU+时间戳


在这里插入图片描述


  • LRU的准确实现,全局时钟+时间戳方案
  • 维护一个全局时钟,每页维护维护一个时间戳,表示这一页的最近使用时间
  • 则选择最近使用时间最早(最小)的页淘汰,所以把上述的D把C给换掉了
  • 算法实现很简单,但是需要遍历找到最小值,时间复杂度较高,不可行
  • 每执行一条指令的时候,就要把页的时间戳进行修改

1.6 LRU+页面栈

  • LRU的准确实现,页码栈方案
    • 新来的页,如果栈空间还够,就加到栈顶
    • 新来的页,如果栈空间不够,则淘汰栈底元素,新来的加再加入栈顶
    • 已有的页,从栈里原来的位置移到栈顶
    • 从栈顶到栈底,是按照最近使用时间戳从大到小的顺序排列的
    • 代码实现:双向链表+Map,当年实习面试好像问的就是这个,时间复杂度仍然不低,所以实际操作系统不用这种算法

在这里插入图片描述


  • 如图,在栈的顶部总是保留最近使用的
  • 然后要使用的就上浮,短时间使用的就下降
  • 这其实是deque
  • 实现代价也不小
  • 双向列表+hash表 ; 已经存在的不换出,但是要把他放到首位,其它的依次下沉;如果不存在,就将新的放在首位,末尾移出

1.7 SCR算法 / Clock算法


  • SCR算法/Clock算法
    • 每个页加一个引用位
    • 每次访问一页时,硬件自动将这个引用位设置为1,代价较小
    • 需要淘汰页时,扫描每一页的引用位,碰到1则置为0,碰到0则淘汰该页(注意这里的1,代表的是访问过的意思,碰到1就是访问过,最近访问过,0就是没访问过,所以碰到1的话,再给你一次机会,置成0,如果转了一圈发现你还是0,就是最近没访问过,那么就要被淘汰了,因为又转了一圈,发现你是没访问过的(最近没有使用),那么根据LRU,肯定是要被淘汰的)
    • 疑问:这个时间复杂度是多少?感觉证明比较复杂
    • 疑问:每次扫描的起点是哪一页?从上次扫描的位置后面开始扫描吗?
    • 为什么说这种算法是LRU的近似实现?
      • 老师说LRU是最近最少使用,这种算法是最近没有使用
      • 这样代价就低了,没执行一条指令,就置位,而且还可以让MMU自动做
        在这里插入图片描述

在这里插入图片描述


  • 效率很高
  • 缺页通常很少,因为有局部性
  • 缺页这个时候,可以转动这个指针,把1变成0
  • 如果缺页很少,那可能会出现所有的R=1,很少出现从1置成0的情况,那么下一次缺页的时候,需要淘汰页,那么需要扫描一圈,把所有的1置为0,然后才能把第一个全是0的页淘汰掉
  • 如此循环,那么每次扫描都需要扫描几乎一圈,那么下一次淘汰页,从下一个位置开始扫描的话,淘汰的就是下一个位置的页
  • 在这种理想情况下,退化为了FIFO(R全是1的情况下,指针进行挨个扫描,会把所有的1变成0,全部变成0就会把这一页换出)
  • 这是最近没有使用来表达最近很少使用
  • 本质原因:在缺页很少的情况下,历史信息一直没有被清零,记录了太长的历史信息,就无法反映出“最近”这段时间的情况
  • 解决办法:定时清除标记位,再加一个扫描指针用于清除,这个指针移动速度要快一些,很像一个时钟,应该定时清除R位,让R位从1置成0
  • 增加一个速度更快的扫描指针,定时清除R位
  • 最近一年没有使用和最近一周没有使用的区别,最近一周才能体现局部性

  • 下图中,横轴是进程的个数
  • 系统内进程增多的时候,每个进程分到的页就少了,每个进程的缺页率就增大了,缺页率太大,那么总是要缺页中断,页换入换出(磁盘读写IO),刚把某一页换出去,又把这一页换进来,CPU利用率就降低了
  • 那么每个进程到底应该分配多少页框?根据局部性原理,一个程序在某一段时间内,用到的数据具有空间局部性,如果页框的数量可以覆盖住这个局部空间的大小,那么就是足够的
  • 如何求出局部空间的大小呢?可以查找别的资料,老师简单的提到了一个工作集算法
  • 可以动态的调整分配给进程的页框数量
  • 但是当进程数增大到一定程度的时候,每个进程分配到的页框数量必然是不够的,这个时候就应该限制进程的数量

在这里插入图片描述


2 总结

  • 内存换入换出的总结,以及前面全部内容的简单总结
    • 在安装linux的时候,都需要在磁盘上分配一个swap分区
    • 内存换入换出实现了,虚拟内存就实现了
    • 虚拟内存实现了,段页结合的实际内存管理就实现了

在这里插入图片描述


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值