安全1601_沈香港_16281077_操作系统lab4
页面置换算法
说明:本实验在加深理解的基础上有参考孙汉武同学实验结果
实验目的以及基本要求
设计和实现最佳置换算法、先进先出置换算法、最近最久未使用置换算法、页面缓冲置换算法以及改进的CLOCK置换算法;通过页面访问序列随机发生器实现对上述算法的测试及性能比较。
一、概要设计
1.1模块
1.2功能
(1)随机生成页面访问序列
(2)模拟运行OPT页面替换算法
(3)模拟运行LRU页面替换算法
(4)模拟运行FIFO页面替换算法
(5)模拟运行PBA页面替换算法
(6)模拟运行改进CLOCK页面替换算法
二、实现
2.1数据结构设计
typedef struct WorkItem
{
int seq;
int priority;
char Used;//访问位
char Modified;//修改位
}WorkItem;
按照实验要求的固定属性
16位,1k页面大小
模拟的物理内存32块
typedef struct MemSchedule
{
WorkItem* WorkSpace = NULL;
int *VisitSeq = NULL;
int N = 64;
int p = 0;
//工作集大小
int e = 5;
int m = 1;
//定义访问序列长度o
int length;
//当前已使用物理块数
int work_len = 0;
//发生替换的物理块号
int change = 0;
float t, r;
// 队列长度
int queue_free_len = 0;
int queue_modified_len = 0;
WorkItem free[2];
WorkItem Modified[2];
}MemSchedule;
2.2随机生成页面访问序列
生成访问页面序列
MemSchedule GeneVisitSeq(int l)
{
MemSchedule schedule1;
schedule1.t = rand() % 1000 / 1000.0;
schedule1.VisitSeq = (int *)malloc(l * sizeof(schedule1.m));
printf("生成随机内存访问序列:\n");
for (int i = 0; i<l; i++)
{
for (int j = 0; j<schedule1.m; j++)
{
schedule1.VisitSeq[i*schedule1.m + j] = rand() % schedule1.e + schedule1.p;
printf("%d ", schedule1.VisitSeq[i*schedule1.m + j]);
}
schedule1.r = rand() % 1000 / 1000.0;
if (schedule1.r<schedule1.t)
{
schedule1.p = (schedule1.p + 1) % schedule1.N;
}
}
printf("\n");
schedule1.length = l*schedule1.m;
schedule1.WorkSpace = (WorkItem *)malloc(schedule1.e * sizeof(WorkItem));
return schedule1;
}
2.3模拟运行OPT页面替换算法
有关算法的分析
当要调入一页而必须淘汰旧页时,应该淘汰以后不再访问的页,或距现在最长时间后要访问的页面。它所产生的缺页数最少,然而,却需要预测程序的页面引用串,这是无法预知的,不可能对程序的运行过程做出精确的断言,不过此理论算法可用作衡量各种具体算法的标准。
算法流程图如下
代码如下
int Opt(MemSchedule s1)
{
//start和finish用于记录时间
clock_t start, finish;
//num表示优先级,每访问一个指令加一,所以优先级最低的就是最久没有被访问的到的,选择其替换
int miss = 0;
start = clock();
printf("***************最佳置换算法*****************\n");
printf("seq\t");
for (int i = 0; i<s1.e; i++)
{
printf("%d\t", i + 1);
}
printf("\n");
for (int i = 0; i<s1.length; i++)
{
int pointer = s1.VisitSeq[i];
printf("%d:\t", pointer);
//判断当前是否还有空闲物理块
if (s1.work_len<s1.e)
{
//此处的flag用于判断当前访问的序列是已经在内存中
int flag = 0;
//扫描一遍当前的内存块,进行更新优先级操作和查询下一个访问的页号是否在内存中
for (int m = 0; m<s1.work_len; m++)
{
if (s1.WorkSpace[m].seq == pointer)
//若序列在内存中则将flag置为1
flag = 1;
}
if (flag == 1)
{
//若下一个访问的页号在内存中,则没有发生缺页,不需要发生替换,change值表示这一次没有
//缺页
s1.change = -1;
}
if (flag == 0)
{
//如下一个要访问的页号不在内存中,则发生缺页,需要直接将新的页号放入下一个空闲块中
//首先更新全部优先级
//直接将下一个空闲快替换
s1.WorkSpace[s1.work_len].seq = pointer;
//将替换变化了的内存块号写入
s1.change = s1.work_len;
//将已使用的内存数量加一
s1.work_len++;
}
//打印信息
for (int k = 0; k<s1.work_len; k++)
{
//如果发生了页面置换,则打印带@的信息
if (k == s1.change)
{
printf("%d@\t", s1.WorkSpace[k].seq);
//缺页率加一
miss++;
}
else
printf("%d\t", s1.WorkSpace[k].seq);
}
//剩下空闲的页面全部打印*
for (int j = 0; j<s1.e - s1.work_len; j++)
{
printf("*\t");
}
}
else
{
//表示没有空闲内存块
//还是使用flag表示当前物理块在内存中是否出现
int flag = 0;
for (int m = 0; m<s1.work_len; m++)
{
if (s1.WorkSpace[m].seq == pointer)
flag = 1;
}
if (flag == 1)
{
//表示内存块已经出现过
s1.change = -1;
}
if (flag == 0)
{
//min表示最小优先级的那个内存块号
int min_pri = 0xffffff;
for (int m = 0; m<s1.work_len; m++)
{
int n = SearchVisitSqe(s1.VisitSeq, i - 1, s1.WorkSpace[m].seq, 0, s1.length - s1