• 操作系统内存换出---15



    有换入,就应该有换出!

    上一节主要讲了内存的换入,那么有换入就必须要有换出。

    要换出就需要考虑该将当前物理内存中那一部分数据换出,这就涉及到相关算法,就和进程的调度算法一样。


    get_free_page

    get_free_page用于向物理内存申请一个新的空闲页面,该函数中肯定就包含了换出的逻辑,因此我们来研究一下该函数的实现:

    page=get_free_page();
    bread_page(page, current->executable->i_dev, nr);
    
    • 1
    • 2

    并不能总是获得新的页,内存是有限的
    在这里插入图片描述


    FIFO页面置换

    在这里插入图片描述
    FIFO算法好吗?

    评价一个算法的好坏,要看该算法在当前场景下,是否符合我们的优化目标,我们的目标是换出一个最不经常会被使用到的页,尽可能减少缺页次数。

    但是FIFO算法在挑选要换出的页时候,并没有考虑到当前页是否经常被使用到,因此FIFO算法并不适合当前的场景。


    MIN页面置换

    在这里插入图片描述
    min算法需要知道将来每个页的使用时间,将最晚使用到的页先换出,但是这也是该算法的致命缺陷,因为我们无法知道某个页将来什么时候会被使用到。


    LRU页面置换

    在这里插入图片描述
    LRU算法高效的原因很大程度上也是因为利用了程序的局部性特点。


    LRU的准确实现,用时间戳

    在这里插入图片描述
    每执行一条指令,都需要进行地址翻译,还要去修改上面这张表中的时间戳,并且还需要考虑溢出情况,这样的实现代价显然过于大了。

    前面无论是多级页表还是TLB,都是为了尽可能减少访存次数,从而提高指令执行效率,因此这里换出算法的设计也必须要考虑到这一点。


    LRU准确实现,用页码栈

    在这里插入图片描述
    每执行一条指令,需要额外访存多次,显然也不是我们想要的结果。


    LRU近似实现 - 将时间计数变为是和否

    在这里插入图片描述

    • 一开始,所有物理页对应的引用位都为0,表示最近都没有被使用过
    • 当程序访问了其中某个页的时候,会将其对应的引用位设置为1,表示最近使用了
    • 而当需要进行换出页时,就将当前指针指向的引用位为1的页清零(下次如果还没被使用,就淘汰你),然后如果遇到了引用位为0的页,就进行淘汰

    Clock算法的分析与改造

    在这里插入图片描述
    由于程序的局部性原理,导致产生缺页现象会比较少。

    缺页产生的比较少,就会导致大量页的引用位被设置为了1,这样当产生了缺页后,整个Clock 算法就退化了FIFO算法了,这显然不合适。

    原始的Clock 算法其实是用最近没有使用的思想来近似最近最少使用,但是这样容易导致算法退化了FIFO。

    为了体现最近最少使用的思想,就额外引入了一个定时清除R位的指针,定时清除指针会定时将当前指向页面的引用位设置为0,然后往后移动一格。

    引入了定时清除指针之后,就可以将那些最近没有被使用到的页的引用位清零,这样就避免由于淘汰指针移动过慢,导致大量近期没有被使用到的页的引用位依旧为0,和近期被使用的页的引用位一样,那么当需要进行页淘汰时,就无法区分出哪一个页是最近最少使用的了,加入定时清除R位后,就符合最近最少使用的思想了,大家好好体会一下。

    • 定时清除指针工作可以由某个时钟中断完成
    • 淘汰指针工作放在缺页时完成

    置换策略有了,还需要解决一个问题

    在这里插入图片描述
    如果给一个进程分配的实际物理页数过多,首先由于内存大小是有限的,分配太多,最大进程数就需要减少,并且请求调页的对内存的高效利用体现也就不明显了,甚至他额外带来的开销会更加影响系统运行。

    如果给一个进程分配的页框过少,那么会导致进程在运行时缺页率升高,调页频繁,导致系统性能严重受损,毕竟读磁盘可是很慢的。

    多进程确实可以提供CPU利用率,但是进程过多,也会导致每个进程分到页框数减小,随之而来的是缺页率飙升,从而大量时间浪费在了页的调度上面,导致CPU利用率急剧下滑。


    程序执行都有其局部性,最好的页框分配数就是能够覆盖掉当前进程执行时的局部范围,当然程序的局部范围求解不易,可以利用相关求解工作集的算法进行求解。

    在这里插入图片描述
    相对而言简单一点的算法就是动态计算,首先给出一个基础页框数,然后随着进程的执行,如果缺页比较多了,就多分配几个,如果少了,就少分配几个,随着时间的推移,最终将达到一个稳定界限。


    小结

    • 用户发出指令 load addr ,解析发现线性地址addr对应的页缺失了,产生对应的页缺失中断
    • 中断执行,从磁盘读取对应的页到内存对应的空闲页面中来,并建立好相关的映射 (换入)
    • 如果此时内存中的没有空闲页了,那么就需要利用clock算法换出一个页到磁盘中去 (换出)

    在这里插入图片描述

    实现换入换出是为了支持虚拟内存,而实现虚拟内存是为了支持段页结合,实现段页是为了实现操作系统对内存的高效管理。

    操作系统高效管理了内存,就可以让程序载入进内存后可以执行起来,程序执行起来后就成为了一个进程。

    因此,操作系统本质是以进程带动的,多进程推进的,同时内存有效工作的一张图

  • 相关阅读:
    行测-图形推理-6-相似图形类
    Mybatis实现(指标状态)的动态sql
    论文查重的时候一定要注意格式和内容
    LeetCode75——Day9
    WebGL编程指南13-纹理贴图原理
    大数据-之LibrA数据库系统告警处理(ALM-12055 证书文件即将过期)
    SpringBoot排除不需要的自动配置类
    小程序源码:修复登录大河盲盒小程序源码,实现运营“玩法自由”,超多功能的盲盒型抽奖挖矿程序源码下载
    (四)Spring Security Oauth2.0 源码分析--客户端端鉴权(token校验)
    【晶振专题】晶振学习笔记——ST AN2867应用手册 1
  • 原文地址:https://blog.csdn.net/m0_53157173/article/details/125998179