操作系统实验三虚拟存储器管理之模拟页面置换算法(FIFOLRU)

news2024/11/26 2:52:18

文章目录

一、概述

 (1)置换算法

 (2)缺页率与命中率

二、先进先出置换算法(FIFO)

   (1)定义

   (2)示例

 (3)Belady异常

 三、最近最久未使用置换算法(LRU)

(1)定义

(2)示例

四、FIFO&LRU置换算法的模拟

   (1)流程图

 (2)完整代码

 (3)实验结果


一、概述

(1)置换算法

        进程运行时,若其访问的页面不在内存中而需要将其调入,但内存已经无空闲空间时,就需要从内存中调出一页程序或者数据,送入磁盘的对换区。

        选择调出页面的算法就称为页面置换算法。常见的页面置换算法有以下四种:

  • 最佳置换算法(OPT)
  • 先进先出页面置换算法(FIFO)
  • 最近最久未使用置换算法(LRU)
  • 时钟置换算法(CLOCL)

(2)缺页率与命中率

        当前访问的页面不在内存中时,此时发生缺页中断,选择合适的页面置换算法来从内存中调出一页程序或者数据,送入磁盘的对换区,与当前要访问的页面进行置换,从而满足当前的访问需求。这种情况就叫缺页,相反,如果当前访问的页面在内存中时,即为命中。二者有如下关系:

  • 缺页率+命中率=1
  • 缺页率=缺页次数/总页面访问次数
  • 命中率=命中次数/总页面访问次数

本次实验重点是模拟先进先出和最近最久未使用算法的执行过程。


二、先进先出置换算法(FIFO)

(1)定义

        优先淘汰那些最早进入内存的页面,即淘汰在内存中驻留时间最久的页面。该算法实现简单,只需把已调入内存的页面根据先后次序链接成队列,设置一个指针总是指向最老的页面。

(2)示例

假定系统为某个进程分配了3个物理块,访问页面依次如下:7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1

按照FIFO算法, 当依次访问页面7,0,1时,由于都不在内存中发生缺页中断,因为有3个物理块且内存空闲,所以可以不用置换页面直接将这三个页面依次放入内存中;当访问页面2时,由于不在内存中,发生缺页中断,此时按照FIFO置换算法将内存中最早进入内存的页面7与2置换,让2进入内存,后面以此类推。

(3)Belady异常

        分配给进程的物理块增多,但是缺页率却不减反增的现象被称之为Belady异常。如图:

 当进程有3个物理块时,缺页次数为9,缺页率为75%

 当进程有4个物理块时,缺页次数为10,缺页率为83.33%

 另外,只有FIFO算法会出现Belady异常,其它算法不会出现这种情况!


 三、最近最久未使用置换算法(LRU)

(1)定义

        选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。该算法为每个页面设置一个访问字段,用来记录页面自上次被访问以来所经历的时间,淘汰页面时选择现有页面中值最大的予以淘汰。

(2)示例

        再对上面的例子采用LRU算法进行页面置换,如图3.25所示。进程第一次对页面 2访问时,将最近最久未被访问的页面7置换出去。然后在访问页面3时,将最近最久未使用的页面1换出。

        LRU算法的性能较好,但需要寄存器和栈的硬件支持。LRU是堆栈类的算法。理论上可以证明,堆栈类算法不可能出现Belady异常。FIFO 算法基于队列实现,不是堆栈类算法。


四、FIFO&LRU置换算法的模拟

(1)流程图

 (2)完整代码

/*
虚拟存储器之页面置换算法的模拟 
测试数据1:20个访问的页面  3个物理块:
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
测试数据2:10个访问页面  2个物理块
4 2 3 0 3 2 1 2 0 1
*/
#include <stdio.h>
#define phy 100
#define page 100//页面最大数
#define phyBlock 100//物理块最大数
int phyBlockNum;//物理块的数量
int pageNum;//页面数量
int pageNumStrList[page];//保存页面号引用串
//初始化队列
void initializeList(int list[], int number)
{
    for (int i = 0; i < number; i++)
    {
        list[i] = -1;
    }
}
//展示当前队列状态
void showList(int list[], int number)
{
    for (int i = 0; i < number; i++)
    {
        printf("%2d", list[i]);
    }
    printf("\n");
}
//展示当前系统内存状态
void showMemoryList(int list[], int phyBlockNum)
{
    for (int i = 0; i < phyBlockNum; i++)
    {
        if (list[i] == -1)
        {
            break;
        }
        printf("  |%d|\t", list[i]); 
    }
    printf("\n");
}
//页面置换结果分析统计 
void informationCount(int missingCount, int replaceCount, int pageNum)
{
    printf("---------------------------结果分析--------------------------\n");
    printf("缺页次数:%d\n", missingCount);
    double a=(double)missingCount/pageNum;//计算缺页率以百分号形式表示 
    printf("缺页率:%.2f%%\n", a*100);
    double result = (double)(pageNum - missingCount) / (double)pageNum;
    printf("置换次数:%d\n", replaceCount);
    printf("------------------------------------------------------------\n");
}
//寻找该页面下次要访问的位置
int getNextPosition(int currentPage, int currentPosition, int strList[], int pageNum)
{
    for (int i = currentPosition + 1; i < pageNum; i++)
    {
        if (strList[i] == currentPage)
        {
            return i;
        }
    }
    return 100;
}
//FIFO:先进先出置换算法
void replacePageByFIFO(int memoryList[], int phyNum, int strList[], int pageNum) {
    int replaceCount = 0; //置换次数
    int missingCount = 0; //缺页次数
    int pointer = 0; //记录当前最早进入内存的下标
    int isVisited = 0;//记录当前页面的访问情况: 0表示未访问,1表示已访问 
    for (int i = 0; i < pageNum; i++) {
        isVisited = 0;
        //判断是否需要置换,内存已满且需要访问的页面不在内存中
        for (int j = 0; j < phyNum; j++) {
            if (memoryList[j] == strList[i]) {
                //1.该页面已经存在内存中
                //修改访问情况
                isVisited = 1;
                //修改访问时间
                printf("%d\t", strList[i]);
                printf("\n");
                break;
            }
            if (memoryList[j] == -1) {
                //2.页面不在内存中且内存未满则直接存入即可 
                memoryList[j] = strList[i];
                //修改访问情况
                isVisited = 1;
                missingCount++;
                printf("%d\t", strList[i]);
                showMemoryList(memoryList, phyNum);
                break;
            }
        }
        //当前页面还未被访问过,需要进行页面置换
        if (!isVisited) {
            //直接把这个页面存到所记录的下标中
            memoryList[pointer] = strList[i];
            pointer++; //下标指向下一个
            //如果到了最后一个,将下标归零
            if (pointer > phyNum - 1) {
                pointer = 0;
            }
            missingCount++;
            replaceCount++;
            printf("%d\t", strList[i]);
            showMemoryList(memoryList, phyNum);
        }
    }
    informationCount(missingCount, replaceCount, pageNum);
}

//LRU:最近最久未使用置换算法
void replacePageByLRU(int memoryList[], int phyNum, int strList[], int pageNum) {
    int replaceCount = 0;//置换次数
    int missingCount = 0;    //缺页次数
    int timeRecord[phy]; //记录内存中最近一次访问至今的时间
    initializeList(timeRecord, phyNum);
    int isVisited = 0;
    //记录已经在内存中的页面数量
    int pageCount = 0;
    for (int i = 0; i < pageNum; i++) {
        isVisited = 0;
        //时间加一
        for (int p = 0; p < pageCount; p++) {
            if (memoryList[p] != -1) {
                timeRecord[p] ++;
            }
        }
        //是否需要置换
        for (int j = 0; j < phyNum; j++) {
            if (memoryList[j] != -1) {
                timeRecord[j] ++;
            }
            if (memoryList[j] == strList[i]) {
                //该页面已经存在内存中
                //修改访问情况
                isVisited = 1;
                //重置访问时间
                timeRecord[j] = -1;
                printf("%d\t", strList[i]);
                printf("\n");
                break;
            }
            if (memoryList[j] == -1) {
                //页面不在内存中且内存未满,直接存入
                memoryList[j] = strList[i];
                pageCount++;
                //修改访问情况
                isVisited = 1;
                //修改访问时间
                timeRecord[j]++;
                missingCount++;
                printf("%d\t", strList[i]);
                showMemoryList(memoryList, phyNum);
                break;
            }
        }
         //不在内存中,则需要进行页面置换
        if (!isVisited) {
            //1.遍历时间记录表,寻找最久未访问的页面所在的内存下标
            int max = 0;
            for (int k = 0; k < phyNum; k++) {
                if (timeRecord[max] < timeRecord[k]) {
                    max = k;
                }
            }
            //2.将该位置的页面换出
            memoryList[max] = strList[i];
            timeRecord[max] = -1;

            missingCount++;
            replaceCount++;
            printf("%d\t", strList[i]);
            showMemoryList(memoryList, phyNum);
        }
    }
    informationCount(missingCount, replaceCount, pageNum);
}
//测试 
int main(int argc, const char* argv[])
{
	printf("------------------虚拟存储器之页面置换算法------------------\n"); 
    printf("请输入内存的物理块数量:");
    scanf("%d", &phyBlockNum);
    //生成内存队列
    int memoryList[phyBlock];
    //初始化内存状态
    initializeList(memoryList, phyBlockNum);
    //showMemoryList(memoryList,phyBlockNum);
    printf("请输入要访问的页面总数:");
    scanf("%d", &pageNum);
    printf("请输入要访问的页面号:");
    for (int i = 0; i < pageNum; i++) {
        scanf("%d", &pageNumStrList[i]);
    }
    printf("------------------------------------------------------------\n");
    int chose;
    while (1)
    {
        printf("★请选择你要执行的操作:(1.FIFO算法 2.LRU算法 3.退出):");
        scanf("%d", &chose);
        switch (chose)
        {
        case 1:
        	printf("------------------------------------------------------------\n");
        	printf("页面号\t");
        	for(int i=0;i<phyBlockNum;i++){
        		printf("物理块%d\t",i+1);
        	}
        	printf("\n");
            replacePageByFIFO(memoryList, phyBlockNum, pageNumStrList, pageNum);
            //重新初始化内存
            initializeList(memoryList, phyBlockNum);
            break;
        case 2:
        	printf("------------------------------------------------------------\n");
            printf("页面号\t");
        	for(int i=0;i<phyBlockNum;i++){
        		printf("物理块%d\t",i+1);
        	}
        	printf("\n");
            replacePageByLRU(memoryList, phyBlockNum, pageNumStrList, pageNum);
            //重新初始化内存
            initializeList(memoryList, phyBlockNum);
            break;
        default:
        	printf("退出成功");
            return 0;
            break;
        }
    }
    return 0;
}

(3)实验结果

最后, 如果本文内容对你有所帮助,记得点赞收藏哈。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/4390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode每日一题——764. 最大加号标志

LeetCode每日一题系列 题目&#xff1a;764. 最大加号标志 难度&#xff1a;普通 文章目录LeetCode每日一题系列题目示例思路题解题目 在一个 n x n 的矩阵 grid 中&#xff0c;除了在数组 mines 中给出的元素为 0&#xff0c;其他每个元素都为 1。mines[i] [xi, yi]表示 g…

谈谈HTTP协议的方法里,GET和POST的区别?我来教你如何回答~

目录 前言 一、什么是GET、POST&#xff1f; 1.1GET 1.2POST 二、如何轻松回答&#xff1f; 第一步、直接盖棺定论&#xff1a; 第二步、谈细节上的区别&#xff1a; 前言 要想回答好这个问题&#xff0c;咱们先来了解以下什么是GET、POST方法&#xff0c;有哪些细节要注…

阿宇wifi球机如何连接手机

首先下载APP&#xff0c;请见以下三种方式&#xff1a; &#xff08;1&#xff09;至APP Store、各大应用市场搜索 “智U”&#xff0c;下载并安装APP。  &#xff08;2&#xff09;登录ezcloud.uniview.com官网&#xff0c;扫描界面右下方智U APP二维码&#xff0c;下载并…

SpringBoot线上服务假死解决,CPU内存正常

背景 开发小伙伴都知道线上服务挂掉&#xff0c;基本都是因为cpu或者内存不足&#xff0c;出现GC频繁OOM之类的情况。本篇文章区别以上的情况给小伙伴们 带来不一样的服务挂掉。 还记得哔哩哔哩713事故中那场诡计多端的0吗&#xff1f; 对就是这个0&#xff0c;和本次事故没关…

Python基础知识入门(二)

Python基础知识入门&#xff08;一&#xff09; 一、数字类型 Python 数字数据类型用于存储数值。数据类型是不允许改变的&#xff0c;如改变数字数据类型的值&#xff0c;将重新分配内存空间。 1.数字函数 函数 描述 abs(x) 返回数字的绝对值。如abs(-10) 返回 10。 fa…

前端小游戏——推箱子

最近刚刚更新完了HTML&#xff0c;CSS的万字总结&#xff0c;有很多人已经学习完了文章&#xff0c;感觉反馈还不错&#xff0c;今天&#xff0c;用HTML&#xff0c;CSS&#xff0c;JS的知识编写了一个童年经典游戏 - 推箱子&#xff0c;供学习参考。 推荐学习专栏&#xff1a…

EdrawMax Ultimate v12.0 图表和流程图

EDraw Max 是一个多合一的应用程序&#xff0c;用作演示构建器、图表创建者、可视化业务规划师和协作空间&#xff08;用于快速共享图表和模型并接收反馈&#xff09;。 该软件可用于哪些潜在用途&#xff1f; 任何人都可以从 EDraw Max 中受益。它所针对的主题和感兴趣的领域…

【EasyRL学习笔记】第十一章 模仿学习

文章目录一、前言二、行为克隆三、逆强化学习四、第三人称视角模仿学习五、序列生成和聊天机器人六、关键词总结七、习题一、前言 模仿学习 (imitation learning&#xff0c;IL) 讨论的问题是&#xff0c;假设我们连奖励都没有&#xff0c;要怎么进行更新以及让智能体与环境交…

黑马学Docker(二)

目录&#xff1a; &#xff08;1&#xff09;容器命令介绍 &#xff08;2&#xff09; 容器命令案例1 &#xff08;3&#xff09;容器命令案例2 &#xff08;4&#xff09;容器命令练习 &#xff08;5&#xff09;数据卷命令 &#xff08;6&#xff09; 数据卷挂在案例1 …

数字孪生:实现保险行业数字化转型

现如今&#xff0c;数据分析在各个行业都在广泛的使用&#xff0c;保险行业也不例外。在数字化浪潮席卷全球的时代&#xff0c;如何利用数字化技术驱动业务增长&#xff0c;实现数字化转型&#xff0c;是目前保险行业需要思考的问题。 可视化技术能够助力保险机构更好地解决互联…

[hive]维度模型分类:星型模型,雪花模型,星座模型|范式|纬度建模|数仓分层

数仓&#xff08;十八&#xff09;数仓建模以及分层总结(ODS、DIM、DWD、DWS、DWT、ADS层) - 墨天轮 一、维度模型分类:星型模型,雪花模型,星座模型 1、星型模型 星型模型中只有一张事实表&#xff0c;以及0张或多张维度表&#xff0c;事实与纬度表通过主键外键相关联&#…

vue项目 API接口封装

vue项目 API接口封装 01.基础配置创建 分别创建如下文件和文件夹 Object │ .env.development │ .env.production └─src├─api│ index.js│ login.js├─utils│ request.js.env.development 和 .env.production 配置生产环境和开发环境移步&#xf…

Java程序员不得不会的124道面试题(含答案)

1&#xff09;Java 中能创建 volatile 数组吗&#xff1f; 能&#xff0c;Java 中可以创建 volatile 类型数组&#xff0c;不过只是一个指向数组的引用&#xff0c;而不是整个数组。我的意思是&#xff0c;如果改变引用指向的数组&#xff0c;将会受到 volatile 的保护&#x…

多线程常见锁的策略

文章目录前言一、乐观锁和悲观锁1.1 定义1.2 生动有趣滴例子1.3 版本号机制二、读写锁2.1 读写锁的由来2.2 生动有趣de例子2.3 ReentrantReadWriteLock 类三、重量级锁与轻量级锁3.1 定义3.2 生动活泼の例子3.3 自旋锁&#xff08;Spin Lock&#xff09;四、公平锁与非公平锁五…

一名程序员的电脑桌面

配置&#xff1a; 酷呆桌面注册表隐藏快捷方式箭头图标开启桌面模式自动隐藏任务栏 酷呆桌面 在选择酷呆之前&#xff0c;一直是使用的Fences&#xff0c;他的桌面切换功能非常赞&#xff0c;适合划分工作区。但由于强迫症实在是忍受不了肉眼可见的掉帧、黑背景bug&#xff0…

简简单单搞一个实用的Android端搜索框

Hello啊老铁们&#xff0c;今天带来一个非常实用的自定义搜索框&#xff0c;包含了搜索框、热门搜索列表、最近搜索列表等常见的功能&#xff0c;有类似的&#xff0c;大家可以直接复用&#xff0c;将会大大节约您的开发时间&#xff0c;有一点&#xff0c;很负责任的告诉大家&…

最全面的Mybatis教程,从“开局”到“通关”,Ready Go!

前言 本文为SSM框架 【Mybatis】 相关知识&#xff0c;MyBatis 是一款优秀的半自动的ORM持久层框架&#xff0c;下边将对Mybatis的简介、Mybatis的CRUD实现&#xff0c;Mybatis的配置文件&#xff0c;Mybatis的日志配置&#xff0c;resultMap详解&#xff0c;分页实现&#xff…

Vulnhub_CengBox

目录 一 环境异常处理 &#xff08;一&#xff09;nat设置无法正常获取地址 1 单用户模式进入命令行 2 passwd更改 3 修改网络配置文件 二 环境测试 &#xff08;一&#xff09;信息收集 1 端口服务 2 目录扫描 &#xff08;二&#xff09;漏洞测试 1 SQL…

SpringBoot项目的创建(一):通过idea的Spring Initializr来创建(需联网以下载SpringBoot相关的模板)

SpringBoot项目的创建1. 环境准备2. 创建SpringBoot项目3. 创建的SpringBoot项目结构如下4. 添加代码测试web页面效果1. 环境准备 安装jdk和idea&#xff0c;tomcat可不安装&#xff0c;有内置的tomcat 2. 创建SpringBoot项目 打包成war后&#xff0c;需要部署到tomcat中再运…

大数据培训技术操作Flume测试监控

大数据培训技术操作Flume测试监控 1&#xff09;修改/opt/module/flume/conf目录下的flume-env.sh配置&#xff1a; JAVA_OPTS”-Dflume.monitoring.typeganglia -Dflume.monitoring.hosts192.168.9.102:8649 -Xms100m -Xmx200m” 2&#xff09;启动Flume任务 [atguiguh…