虚存管理OS实验[推荐]_虚存管理os实验
虚存管理OS实验[推荐]由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“虚存管理os实验”。
实验三 虚存管理
一、实验目的1.加深对存储管理概念的理解。
2.深入了解Windows内存管理机制。
3.理解内存分配原理,特别是以页面为单位的虚拟内存分配方法。4.掌握页式虚拟存储技术。
5.掌握“最不频繁使用淘汰算法”,即LFU页面淘汰算法。
二、理论基础
1.页式存储管理技术。2.虚拟存储管理技术。
三、实验要求
1.编写程序实现简单的虚存管理。
2.实验具体包括:(1)设计并实现一个虚存管理程序,模拟一个单道程序的页式存储管理,用一个一维数组模拟实存空间,用一个文本文件模拟辅存空间;(2)建立一张一级页表;
(3)编写函数随机产生访存请求,访存操作包括读取、写入、执行等三种类型;(4)编写函数响应访存请求,完成虚地址到实地址的定位及读/写/执行操作,同时判断并处理缺页中断;(5)实现LFU页面淘汰算法。3.实验结束提交书面实验报告。
四、实验环境
1.运行Windows操作系统的PC机一台。
2.PC机上安装Visual C++ 6.0开发工具软件。
五、实验内容
1.2.3.4.建立“Win32 Console Application”工程“vmm”。建立“C/C++ Header File”头文件“vmm.h”,文件内容参见“程序代码”。建立“C++ Source File”源文件“vmm.cpp”,文件内容参见“程序代码”。建立“Text File”文本文件“vmm_auxMem.txt”,模拟辅存空间,文件内容可以输入任意字符(字符数多于512个)。
5.运行程序并认真观察和分析程序的运行结果。
七、程序代码
头文件“vmm.h” #ifndef VMM_H #define VMM_H
/* 模拟辅存的文件路径 */ #define AUXILIARY_MEMORY “vmm_auxMem.txt”
/* 页面大小(字节)*/
#define PAGE_SIZE 4 /* 虚存空间大小(字节)*/ #define VIRTUAL_MEMORY_SIZE(64 * 4)/* 实存空间大小(字节)*/
#define ACTUAL_MEMORY_SIZE(32 * 4)/* 总虚页数 */ #define PAGE_SUM(VIRTUAL_MEMORY_SIZE / PAGE_SIZE)/* 总物理块数 */ #define BLOCK_SUM(ACTUAL_MEMORY_SIZE / PAGE_SIZE)
/* 可读标识位 */ #define READABLE 0x01u /* 可写标识位 */ #define WRITABLE 0x02u /* 可执行标识位 */ #define EXECUTABLE 0x04u
/* 页表项 */ typedef struct { unsigned int blockNum;//物理块号
BOOL filled;//页面装入特征位
BYTE proType;//页面保护类型
BOOL edited;//页面修改标识
unsigned long auxAddr;//外存地址 unsigned long count;//页面使用计数器
} PageTableItem, *Ptr_PageTableItem;
/* 访存请求类型 */ typedef enum {
REQUEST_READ, REQUEST_WRITE,REQUEST_EXECUTE } MemoryAcceRequestType;
/* 访存请求 */ typedef struct { MemoryAcceRequestType reqType;//访存请求类型
unsigned long virAddr;//虚地址 BYTE value;//写请求的值
} MemoryAcceRequest, *Ptr_MemoryAcceRequest;
/* 访存错误代码 */
typedef enum { ERROR_READ_DENY, //该页不可读
ERROR_WRITE_DENY, //该页不可写
ERROR_EXECUTE_DENY, //该页不可执行
ERROR_INVALID_REQUEST, //非法请求类型
ERROR_OVER_BOUNDARY, //地址越界
ERROR_FILE_OPEN_FAILED, //文件打开失败 ERROR_FILE_CLOSE_FAILED, //文件关闭失败 ERROR_FILE_SEEK_FAILED, //文件指针定位失败 ERROR_FILE_READ_FAILED, //文件读取失败 ERROR_FILE_WRITE_FAILED //文件写入失败
} ERROR_CODE;
/* 产生访存请求 */ void do_request();/* 响应访存请求 */ void do_response();/* 处理缺页中断 */ void do_page_fault(Ptr_PageTableItem);/* LFU页面替换 */ void do_LFU(Ptr_PageTableItem);/* 装入页面 */ void do_page_in(Ptr_PageTableItem, unsigned int);/* 写出页面 */ void do_page_out(Ptr_PageTableItem);/* 错误处理 */ void do_error(ERROR_CODE);/* 打印页表相关信息 */ void do_print_info();/* 获取页面保护类型字符串 */ char *get_proType_str(char *, BYTE);#endif
源文件“vmm.cpp” #include #include #include #include #include “vmm.h”
/* 页表 */ PageTableItem pageTable[PAGE_SUM];/* 实存空间 */
BYTE actMem[ACTUAL_MEMORY_SIZE];/* 用文件模拟辅存空间 */ FILE *ptr_auxMem;/* 物理块使用标识 */ bool blockStatus[BLOCK_SUM];/* 访存请求 */ Ptr_MemoryAcceRequest ptr_memAccReq;
/* 初始化环境 */ void do_init(){
srand((unsigned int)time(NULL));for(int i = 0;i
pageTable[i].filled = false;pageTable[i].edited = false;pageTable[i].count = 0;/* 使用随机数设置该页的保护类型 */ switch(rand()% 7){
case 0: { pageTable[i].proType = READABLE;break;} case 1: { pageTable[i].proType = WRITABLE;break;} case 2: {
} {
} case 4: { pageTable[i].proType = READABLE | EXECUTABLE;pageTable[i].proType = EXECUTABLE;break;case 3:
pageTable[i].proType = READABLE | WRITABLE;break;
break;} case 5: { pageTable[i].proType = WRITABLE | EXECUTABLE;
} case 6: {
} pageTable[i].proType = READABLE | WRITABLE | EXECUTABLE;break;break;default: break;
} /* 设置该页对应的辅存地址,本程序为实现简单采用顺序设置的方式,可替换成其他设置方式,但须注意每个页表项对应的辅存地址均应为PAGE_SIZE的整数倍 */
}
/* 响应请求 */ void do_response(){
} {
} pageTable[i].auxAddr = i * PAGE_SIZE * 2;for(int j = 0;j
/* 检查地址是否越界 */ if(ptr_memAccReq->virAddr
{
} ptr_memAccReq->virAddr >= VIRTUAL_MEMORY_SIZE)do_error(ERROR_OVER_BOUNDARY);return;
/* 计算页号和页内偏移值 */ pageNum = ptr_memAccReq->virAddr / PAGE_SIZE;offAddr = ptr_memAccReq->virAddr % PAGE_SIZE;printf(“页号为:%ut页内偏移为:%un”, pageNum, offAddr);/* 获取对应页表项 */ ptr_pageTabIt = &pageTable[pageNum];
/* 根据特征位决定是否产生缺页中断 */ if(!ptr_pageTabIt->filled){ }
actAddr = ptr_pageTabIt->blockNum * PAGE_SIZE + offAddr;printf(“实地址为:%un”, actAddr);
/* 检查页面访问权限并处理访存请求 */ switch(ptr_memAccReq->reqType){
case REQUEST_READ: //读请求 {
ptr_pageTabIt->count++;if(!(ptr_pageTabIt->proType & READABLE))//页面不可读 { do_error(ERROR_READ_DENY);do_page_fault(ptr_pageTabIt);return;} /* 读取实存中的内容 */ printf(“读操作成功:值为%02Xn”, actMem[actAddr]);break;} case REQUEST_WRITE: //写请求 {
ptr_pageTabIt->count++;if(!(ptr_pageTabIt->proType & WRITABLE))//页面不可写 { do_error(ERROR_WRITE_DENY);
}
return;} /* 向实存中写入请求的内容 */ actMem[actAddr] = ptr_memAccReq->value;ptr_pageTabIt->edited = true;
printf(“写操作成功n”);break;} case REQUEST_EXECUTE: //执行请求 {
ptr_pageTabIt->count++;if(!(ptr_pageTabIt->proType & EXECUTABLE))//页面不可执行 { do_error(ERROR_EXECUTE_DENY);return;}
printf(“执行成功n”);break;} default: //非法请求类型 {
}
do_error(ERROR_INVALID_REQUEST);return;}
/* 处理缺页中断 */ void do_page_fault(Ptr_PageTableItem ptr_pageTabIt){ printf(“产生缺页中断,开始进行调页...n”);
for(unsigned int i = 0;i
if(!blockStatus[i]){
/* 读辅存内容,写入到实存 */ do_page_in(ptr_pageTabIt, i);
/* 更新页表内容 */ ptr_pageTabIt->blockNum = i;ptr_pageTabIt->filled = true;ptr_pageTabIt->edited = false;ptr_pageTabIt->count = 0;
}
blockStatus[i] = true;
return;} } /* 没有空闲物理块,进行页面替换 */ do_LFU(ptr_pageTabIt);
/* 根据LFU算法进行页面替换 */ void do_LFU(Ptr_PageTableItem ptr_pageTabIt){
}
/* 将辅存内容写入实存 */ void do_page_in(Ptr_PageTableItem ptr_pageTabIt, unsigned int blockNum)printf(“没有空闲物理块,开始进行LFU页面替换...n”);for(unsigned int i = 0, min = 0xFFFFFFFF, page = 0;i
if(pageTable[i].count
} min = pageTable[i].count;page = i;} printf(“选择第%u页进行替换n”, page);if(pageTable[page].edited){ /* 页面内容有修改,需要写回至辅存 */ printf(“该页内容有修改,写回至辅存n”);} do_page_out(&pageTable[page]);pageTable[page].filled = false;pageTable[page].count = 0;/* 读辅存内容,写入到实存 */ do_page_in(ptr_pageTabIt, pageTable[page].blockNum);
/* 更新页表内容 */ ptr_pageTabIt->blockNum = pageTable[page].blockNum;ptr_pageTabIt->filled = true;ptr_pageTabIt->edited = false;ptr_pageTabIt->count = 0;printf(“页面替换成功n”);
{
unsigned int readNum;if(fseek(ptr_auxMem, ptr_pageTabIt->auxAddr, SEEK_SET)
{ sizeof(BYTE), PAGE_SIZE, ptr_auxMem))>物理块%un“, ptr_pageTabIt->auxAddr, blockNum);}
/* 将被替换页面的内容写回辅存 */ void do_page_out(Ptr_PageTableItem ptr_pageTabIt){ unsigned int writeNum;
} if(fseek(ptr_auxMem, ptr_pageTabIt->auxAddr, SEEK_SET)blockNum * PAGE_SIZE,sizeof(BYTE), PAGE_SIZE, ptr_auxMem))>辅存地址%un”, ptr_pageTabIt->auxAddr, ptr_pageTabIt->blockNum);
/* 错误处理 */ void do_error(ERROR_CODE code){
switch(code){
case ERROR_READ_DENY: { printf(“访存失败:该地址内容不可读n”);break;} case ERROR_WRITE_DENY:
{ printf(“访存失败:该地址内容不可写n”);break;} case ERROR_EXECUTE_DENY: {
} {
} printf(“访存失败:该地址内容不可执行n”);break;
case ERROR_INVALID_REQUEST: printf(“访存失败:非法访存请求n”);break;case ERROR_OVER_BOUNDARY: { printf(“访存失败:地址越界n”);} { break;case ERROR_FILE_OPEN_FAILED: printf(“系统错误:打开文件失败n”);break;} case ERROR_FILE_CLOSE_FAILED: { printf(“系统错误:关闭文件失败n”);break;} case ERROR_FILE_SEEK_FAILED: {
} printf(“系统错误:文件指针定位失败n”);break;case ERROR_FILE_READ_FAILED: { printf(“系统错误:读取文件失败n”);} {
} break;case ERROR_FILE_WRITE_FAILED: printf(“系统错误:写入文件失败n”);break;
}
} default: { } printf(“未知错误:没有这个错误代码n”);
/* 产生访存请求 */ void do_request(){
}
/* 打印页表 */ void do_print_info(){ /* 随机产生请求地址 */ ptr_memAccReq->virAddr = rand()% VIRTUAL_MEMORY_SIZE;/* 随机产生请求类型 */ switch(rand()% 3){
} case 0: //读请求 {
ptr_memAccReq->reqType = REQUEST_READ;printf(“产生请求:n地址:%ut类型:读取n”, ptr_memAccReq->virAddr);break;} case 1: //写请求 {
} ptr_memAccReq->reqType = REQUEST_WRITE;/* 随机产生待写入的值 */ ptr_memAccReq->value = rand()% 0xFFu;printf(“产生请求:n地址:%ut类型:写入t值:%02Xn”,ptr_memAccReq->virAddr, ptr_memAccReq->value);break;case 2: {
} ptr_memAccReq->reqType = REQUEST_EXECUTE;printf(“产生请求:n地址:%ut类型:执行n”, ptr_memAccReq->virAddr);break;default: break;
} char str[4];printf(“页号t块号t装入t修改t保护t计数t辅存n”);for(unsigned int i = 0;i
}
pageTable[i].blockNum, pageTable[i].filled,pageTable[i].edited, get_proType_str(str, pageTable[i].proType), pageTable[i].count, pageTable[i].auxAddr);
/* 获取页面保护类型字符串 */ char *get_proType_str(char *str, BYTE type){
} if(type & READABLE)str[0] = 'r';else str[0] = '-';if(type & WRITABLE)else str[1] = '-';if(type & EXECUTABLE)str[2] = 'x';else str[2] = '-';str[3] = ' ';return str;str[1] = 'w';int main(int argc, char* argv[]){
if(!(ptr_auxMem = fopen(AUXILIARY_MEMORY, “r+”))){
}
do_init();do_print_info();do_error(ERROR_FILE_OPEN_FAILED);exit(1);ptr_memAccReq =(Ptr_MemoryAcceRequest)malloc(sizeof(MemoryAcceRequest));/* 在循环中模拟访存请求与处理过程 */
while(true){
}
} do_request();do_response();do_print_info();/* 随机休眠5~10秒 */ Sleep(5000 +(rand()% 5)* 5000);if(fclose(ptr_auxMem)== EOF){
} do_error(ERROR_FILE_CLOSE_FAILED);exit(1);return(0);
八、实验测试(程序运行结果显示)