课程设计设计题目 模拟实现请求分页虚存页面替换算法

[设计目的]

1. 理解虚拟内存和请求分页管理机制的基本概念;

2. 学习不同的页面替换算法,包括但不限于FIFO、LRU、OPT等;

3. 通过模拟实现页面替换算法,加深对操作系统内存管理的理解。

[设计要求]

在操作系统当中,设计并实现一个模拟环境,用于模拟请求分页虚拟存贮中的页面替换过程。

需要创建一个模拟的内存环境,包括内存页框、页面、进程等概念。

需要实现页面的加载、访问和替换过程,并能够追踪页面的访问情况。

在操作系统中,对FIFO、LRU、OPT等页面替换算法进行模拟,分析并比较它们的性能和效率。

编写代码实现每种算法,并确保它们能够在模拟环境中正常运行。

收集并分析不同算法在不同工作负载下的性能数据,比如页面错误率、CPU 时间等。

比较不同算法的优缺点,并探讨它们在实际系统中的应用场景

[设计思想及内容]

设计思想是创建一个模拟环境,其中包含一个固定大小的内存框架集合,以及一个页面访问序列。通过模拟页面访问过程,展示不同页面替换算法的工作方式及其对系统性能的影响。

[数据结构设计]

核心数据结构主要涉及内存管理和页面替换算法所需的元素。以下是核心数据结构的定义:

页面(_Page):包含页面ID等信息。

页面队列(_PageQueue):用于存储进程中的页面序列。

进程(_Process):包含页面队列和页面总数。

内存块(_Block):表示内存中的一个存储单元,包含页面指针、状态和最后访问时间。

内存块队列(_BlockQueue):用于表示内存中的块序列。

[程序源码]

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<sys/time.h>
#include<unistd.h>
#include<stdlib.h>

#define NULL ((void *)0)
#define BUSY 1
#define AVA  0
#define BLOCKNUMBER 3

//以下为数据结构的定义

long Time = 0;
//页面
typedef struct _Page{
    int id;
}Page;

//页面队列
typedef struct _PageQueue{
    Page page;
    struct _PageQueue *next;
}PageQueue;

//进程
typedef struct _Process{
    PageQueue pages;
    int length;
}Process;

//内存块
typedef struct _Block{
    Page *page;
    int state;
    long lasttime;
}Block;

//内存块队列
typedef struct _BlockQueue{
    Block block;
    struct _BlockQueue *next;
}BlockQueue;

//重要函数的实现
//初始化页面队列
PageQueue *InitPageQueue(int pagesize,int maxpageID){
    PageQueue *head = NULL;
    PageQueue *p = NULL;
    PageQueue *q = NULL;
    for (int i = 0; i < pagesize; i++)
    {
        p = (PageQueue *)malloc(sizeof(PageQueue));
        p->page.id = rand() % (maxpageID + 1);
        p->next = NULL;
        printf("%d ",p->page.id);
        if(head == NULL) head = p;
        else q->next = p;
        q = p ;
    }
    printf("\n");
    return head;
}


//初始化进程
Process *InitProcess(Process *process,int pagesize,int maxpageID){
    process = (Process *)malloc(sizeof(Process));
    printf("进程初始化\n");
    process->length = pagesize;
    process->pages.next = InitPageQueue(pagesize,maxpageID);
    return process;
}

//内存初始化
BlockQueue *InitBlockQueue(int size){
    BlockQueue *head = NULL;
    BlockQueue *p = NULL;
    BlockQueue *q = NULL;
    for (int i = 0; i < size; i++)
    {
        p = (BlockQueue *)malloc(sizeof(BlockQueue));
        p->block.page = (Page *)malloc(sizeof(Page));
        p->block.page->id = 0;
        p->block.state = AVA;
        p->block.lasttime = 0;
        if(head == NULL) head = p;
        else q->next = p;
        q = p;
    }
    q->next = NULL;
    return head;
}


//获取当前块队列的长度
int Get_BlockQueue_Length(BlockQueue *blockqueue){
    BlockQueue *presentblock;
    presentblock = blockqueue;
    int queuelength = 0 ;
    while (presentblock != NULL)
    {
        queuelength++;
        presentblock = presentblock->next;
    }
    return queuelength;
}

//搜索空闲块
BlockQueue *Search_AVA_Block(BlockQueue *blockqueue){
    BlockQueue *presntblock;
    presntblock = blockqueue;
    while (presntblock != NULL)
    {
        if(presntblock->block.state == AVA) return presntblock;
        else presntblock = presntblock->next;
    }
    return NULL;
}

//清空块队列
void EmptyBlock(BlockQueue *blockqueue){
    
    BlockQueue *presentblock;
    presentblock = blockqueue;
    while(presentblock != NULL){
        presentblock->block.page = NULL;
        presentblock->block.state = AVA;
        presentblock->block.lasttime = 0;
        presentblock = presentblock->next;
    }
}

//搜索特定页面
BlockQueue *SearchPage(BlockQueue *blockqueue,Page page){
    BlockQueue *p;
    p = blockqueue;
    while(p != NULL){
        if(p->block.page->id == page.id){ 
            return p;
        }else{ 
        p = p->next;
        }
    return NULL;
    }
}

//搜索内存中停留最久的块
BlockQueue *SreachOldestBlock(BlockQueue *blockqueue){
    BlockQueue *p,*oldestblock;
    p = blockqueue;
    oldestblock = p;
    long oldest = p->block.lasttime;
    while(p != NULL){
        if(p->block.lasttime < oldest){
            oldest = p->block.lasttime;
            oldestblock = p;
        }
        p = p->next;
    }
    return oldestblock;
}

//搜索内存中持续最长时间不被访问的页面
BlockQueue *SearchLongestBlock(BlockQueue *blockqueue,PageQueue *page){
   BlockQueue *p = blockqueue, *longestblock;
    PageQueue *q = page->next;
    if (p == NULL) return p;
    longestblock = p;
    int max_count = 0;
    while (p != NULL){
        int count = 0;
        while(q != NULL){
            count++;
            if(p->block.page->id == q->page.id) break;
            q = q->next;
        }
        if(count > max_count){
            max_count = count;
            longestblock = p;
        }
        q = page->next;
        p = p->next;
    }
    return longestblock;
}


//返回块号
int GetBlockLable(BlockQueue *blockQueue, BlockQueue *goalBlock) {
    BlockQueue *p = blockQueue;
    int count = 1;
    while (p != goalBlock) {
        p = p->next;
        count++;
    }
    return count;
}


//打印块信息
void PrintBlockList(BlockQueue *blockQueue, int pageID, int number) {
    BlockQueue *presentBlock = blockQueue;
    for (int i = 0; i < Get_BlockQueue_Length(blockQueue); i++) {
        printf("页框%d ", i + 1);
        if (presentBlock->block.state == AVA) {
            printf("|     |\n");
        } else {
            if (presentBlock->block.page->id != pageID) {
                printf("|  %d  |\n", presentBlock->block.page->id);
            } else {
                switch (number) {
                    case 1:
                        printf("|  %d  |  命中! 主存已存在该页面,位于页框%d\n", pageID, GetBlockLable(blockQueue, presentBlock));
                        break;
                    case 2:
                        printf("|  %d  |  缺页! 主存不存在该页面,载入空闲页框%d\n", pageID, GetBlockLable(blockQueue, presentBlock));
                        break;
                    case 3:
                        printf("|  %d  |  缺页! 主存不存在该页面,替换页框%d\n", pageID, GetBlockLable(blockQueue, presentBlock));
                        break;
                    default:
                        break;
                }
            }
        }
        presentBlock = presentBlock->next;
    }
    printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
}



//替换算法的实现

//FIFO
void FIFO(BlockQueue *blockQueue, Process *process) {
    PageQueue *currentPage = process->pages.next;
    while (currentPage != NULL) {
        if (SearchPage(blockQueue, currentPage->page) != NULL) {
            PrintBlockList(blockQueue, currentPage->page.id, 1);
        } else {
            BlockQueue *avaBlock = Search_AVA_Block(blockQueue);
            if (avaBlock != NULL) {
                avaBlock->block.state = BUSY;
                avaBlock->block.lasttime = Time++;
                avaBlock->block.page = (Page *) malloc(sizeof(Page));
                avaBlock->block.page->id = currentPage->page.id;
                PrintBlockList(blockQueue, currentPage->page.id, 2);
            } else {
                avaBlock = SreachOldestBlock(blockQueue); 
                avaBlock->block.lasttime = Time++;
                avaBlock->block.page->id = currentPage->page.id;
                PrintBlockList(blockQueue, currentPage->page.id,3);
            }
        }
        currentPage = currentPage->next;
    }
}


//LRU
void LRU(BlockQueue *blockQueue, Process *process) {
    PageQueue *currentPage = process->pages.next;
    while (currentPage != NULL) {
        BlockQueue *searchedBlock = SearchPage(blockQueue, currentPage->page);
        if (searchedBlock != NULL) {
            searchedBlock->block.lasttime = Time++;
            PrintBlockList(blockQueue, currentPage->page.id, 1);
        } else {
            BlockQueue *avaBlock = Search_AVA_Block(blockQueue);
            if (avaBlock != NULL) {
                avaBlock->block.state = BUSY;
                avaBlock->block.lasttime = Time++;
                avaBlock->block.page = (Page *) malloc(sizeof(Page));
                avaBlock->block.page->id = currentPage->page.id;
                PrintBlockList(blockQueue, currentPage->page.id, 2);
            } else {
                avaBlock = SreachOldestBlock(blockQueue);
                avaBlock->block.lasttime = Time++;
                avaBlock->block.page->id = currentPage->page.id;
                PrintBlockList(blockQueue, currentPage->page.id, 3);
            }
        }
        currentPage = currentPage->next;
    }
}


//OPT
void OPT(BlockQueue *blockQueue,Process *process){
    PageQueue *currentPage = process->pages.next;
    while (currentPage != NULL) {
        if (SearchPage(blockQueue, currentPage->page) != NULL) {
            PrintBlockList(blockQueue, currentPage->page.id,1);
        } else {
            BlockQueue *avaBlock = Search_AVA_Block(blockQueue);
            if (avaBlock != NULL) {
                avaBlock->block.state = BUSY;
                avaBlock->block.lasttime = Time++;
                avaBlock->block.page = (Page *) malloc(sizeof(Page));
                avaBlock->block.page->id = currentPage->page.id;
                PrintBlockList(blockQueue, currentPage->page.id, 2);
            } else {
                avaBlock = SearchLongestBlock(blockQueue,currentPage);
                avaBlock->block.lasttime = Time++;
                avaBlock->block.page->id = currentPage->page.id;
                PrintBlockList(blockQueue, currentPage->page.id, 3);
            }
        }
        currentPage = currentPage->next;
    }
}


int main(){
        Process *process,*p;
        int pageNumber;
        int casenum;
        PageQueue *pages;
        BlockQueue *blockqueue;
        blockqueue = InitBlockQueue(BLOCKNUMBER);
        printf("请输入进程页面数:");
        scanf("%d",&pageNumber);
        printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
        printf("主存页框数: %d  进程页面数:%d\n",BLOCKNUMBER,pageNumber);
        printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
        p = InitProcess(process,pageNumber,pageNumber);
        printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
        printf("1.FIFO\t2.LRU\t3.OPT\t0.exit\n");
        printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
        printf("请选择要使用的替换算法:");
        scanf("%d",&casenum);

        switch (casenum)
        {
        case 1 :
            FIFO(blockqueue,p);
            break;

        case 2 :
            LRU(blockqueue,p);
            break;
        
        case 3 :
            OPT(blockqueue,p);
            break;

        case 0 :
            return 0;    

        default:
            printf("输入错误!");
            break;
        }

}


简要的代码思路解释:

我们知道OPT算法在现实中是无法实现的,但是我们这里采用了比较投机的算法简单的模拟了一下

OPT算法:最佳选择算法

假设我们现在有三个内存块,而来了六个进程,我们很容易知道,当前面是不一样的三个进入内存块之后,势必会产生页面置换,我们遍历现在内存块中的内容,和后面的进程进行匹配,相同则记录两个进程的“距离”,不同的就即为无穷大或者-1,大家按自己的习惯来就好,起个区分作用就行

FIFO算法:先进先出算法

这里我们设置了一个变量lasttime,意思是持续时间,每当进程进入之后,我们就让在内存中的进程的lasttime的值全都+1,替换时替换掉 lasttime值最小的进程所在的内存块。

LRU算法:最近最久未使用算法

这里我们有一个十分巧妙的地方,就是和FIFO采用的一样的lasttime,这里的lasttime的值更新条件和FIFO中有所区别,我们不仅会全都+1,而且在进程被调用的时候还会给被调用的进程额外+1,怎么说呢,还是喜欢举例子,3个内存块,进程分别为1 2 3 1 2 3 ,当调用到第四个进程(这里是1),那么此时1 2 3 不仅同时增加一个时间单位,而且 1 还会再被增加一个时间单位,因为他被调用了,这样在置换页面的时候,我们还是优先置换lasttime值最小的内容

这么做的优点:统一置换函数,而且减少变量设计,编程实现更加高效

[设计实现展示(可附截图说明)]

OPT算法

FIFO算法

LRU算法

[课程设计出现问题及解决方法]

问题1:页面替换算法的性能比较不明显。 解决方法:增加页面访问序列的长度,确保有足够的数据来观察算法的性能差异。

问题2:内存框架大小固定,限制了模拟的灵活性。 解决方法:允许用户输入内存框架的大小,使模拟更加灵活。

问题3:置换算法在置换时出现和预期效果不匹配的情况。解决办法:通过请教老师,老师说search_oldest_block函数的if逻辑判断有问题,请过debug调试之后发现问题所在,使得程序达到了预期效果。

【参考资料】

https://blog.csdn.net/qq_32767041/article/details/85237988

模拟实现请求分页虚存页面替换算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值