通过实现页面置换的四种算法,理解虚拟存储器的概念、实现方法,页面分配的总体原则、进程运行时系统是怎样选择换出页面的,并分析四种不同的算法各自的优缺点是哪些。
以下算法都要实现:
#include
#include
#include
typedef struct item
{
int num; //页号
int time; //LRU算法的等待时间
}Pro;
int pageNum; //系统分配给作业的主存中的页面数
int memoryNum; //可用内存页面数
void print(Pro* page1); //打印当前主存中的页面
int Search(int num1, Pro* memory1);
int main(void)
{
int i;
int curmemory; //调入内存中的页面个数
int missNum; //缺页次数
float missRate; //缺页率
char c; //得到用户的输入字符,来选择相应的置换算法
Pro* page; //作业页面集
Pro* memory; //内存页面集
printf("请输入所需要访问的页面总数:");
scanf_s("%d", &pageNum);
printf("请输入物理块的数量:");
scanf_s("%d", &memoryNum);
page = (Pro*)malloc(sizeof(Pro) * pageNum);
memory = (Pro*)malloc(sizeof(Pro) * memoryNum);
printf("访问的页面号将随机生成,生成的页面号为:");
srand((unsigned int)time(NULL));
for (i = 0; i < pageNum; i++)
{
//scanf_s("%d", &page[i].num);
page[i].num= rand() % (pageNum-1);
printf("%d ",page[i].num);
page[i].time = 0; //等待时间开始默认为0
}
printf("\n");
do {
for (i = 0; i < memoryNum; i++) //初始化内存中页面
{
memory[i].num = -1; //页面为空用-1表示
memory[i].time = -1;
}
printf("----- 1.FIFO 2.OPT 3.LRU 4.LFU ----- \n");
printf("*****请选择操作类型,按其它键结束******\n");
//fflush(stdin);
getchar();
scanf_s("%c", &c);
i = 0;
curmemory = 0;
if (c == '1') //FIFO页面置换
{
missNum = 0;
printf("页面置换情况: \n");
for (i = 0; i < pageNum; i++)
{
if (Search(page[i].num, memory) < 0)//若在内存中没有找到该页面
{
missNum++;
memory[curmemory].num = page[i].num;
print(memory);
curmemory = (curmemory + 1) % memoryNum; //找出最先进入内存的页面
}else
print(memory);
}//end for
missRate = (float)missNum / pageNum;
printf("缺页次数:%d 缺页率: %f\n", missNum, missRate);
}//end if
if (c == '2') //OPT页面置换算法
{
missNum = 0;
curmemory = 0;
printf("页面置换情况: \n");
for (i = 0; i < pageNum; i++)
{
if (Search(page[i].num, memory) < 0)//若在内存中没有找到该页面
{
//找出未来最长时间内不再被访问的页面
int tem;
int opt = 0;
for (int k = 0; k < memoryNum; k++)
{
if (memory[k].num == -1)
{
curmemory = k;
break;
}
tem = 0; //页面k在未来tem时间内不会出现
int j;
for (j = i + 1; j < pageNum; j++)
{
if (page[j].num == memory[k].num)
{
if (tem > opt)
{
opt = tem;
curmemory = k;
}
break;
}
else tem++;
}
if (j == pageNum)
{
opt = tem;
curmemory = k;
}
}
missNum++;
memory[curmemory].num = page[i].num;
print(memory);
}
else
print(memory);
}//end for
missRate = (float)missNum / pageNum;
printf("缺页次数:%d 缺页率: %f\n", missNum, missRate);
}//end if
if (c == '3') //LRU页面置换算法
{
missNum = 0;
curmemory = 0;
printf("页面置换情况: \n");
for (i = 0; i < pageNum; i++)
{
int rec = Search(page[i].num, memory);
if (rec < 0) //若在内存中没有找到该页面
{
missNum++;
for (int j = 0; j < memoryNum; j++) //找出最近最久未使用的页面
if (memory[j].time == -1) {
curmemory = j; break;
}
else if (memory[j].time > memory[curmemory].time)
curmemory = j;
memory[curmemory].num = page[i].num;
memory[curmemory].time = 0;
print(memory);
}
else
{
memory[rec].time = 0;
print(memory);
}
for (int j = 0; j < memoryNum; j++) //内存中的所有页面等待时间+1
if (memory[j].num != -1)
memory[j].time++;
}//end for
missRate = (float)missNum / pageNum;
printf("缺页次数:%d 缺页率: %f\n", missNum, missRate);
}//end if
if(c == '4') //LFU页面置换算法
{
missNum = 0;
curmemory = 0;
int *counter; // 每个页面分配一个计数器
counter = (int*)calloc(pageNum, sizeof(int));
for (i = 0; i < pageNum;i++)
counter[i] = 0; // 每个页面初始访问0次
printf("页面置换情况: \n");
for (i = 0; i < pageNum; i++)
{
int rec = Search(page[i].num, memory);
if (rec < 0) //若在内存中没有找到该页面
{
missNum++;
// 寻找在物理块中的页面里访问次数最少的
int min = 0;
for (int j = 0; j < memoryNum; j++)
{
if (memory[j].num == -1)
{
min = j;
break;
}
else if(counter[memory[j].num] < counter[memory[min].num])
min = j;
}
memory[min].num = page[i].num;
counter[page[i].num]++; // 最近使用次数+1
print(memory);
} // 若在内存中找到了页面
else
{
counter[page[i].num]++; // 最近使用次数+1
}
}//end for
missRate = (float)missNum / pageNum;
printf("缺页次数:%d 缺页率: %f\n", missNum, missRate);
}//end if
} while (c == '1' || c == '2' || c == '3'|| c == '4');
return 0;
}
void print(Pro* memory1)//打印当前的页面
{
int j;
for (j = 0; j < memoryNum; j++)
printf("%d ", memory1[j].num);
printf("\n");
}
//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1
int Search(int num1, Pro* memory1)
{
int j;
for (j = 0; j < memoryNum; j++)
{
if (num1 == memory1[j].num)
return j;
}
return -1;
}