C语言页式虚存管理

peter-hill 学生  2017-11-20 10:28:26

实验二 页式虚存管理
1.实验内容:模拟请求页式存储管理中硬件的地址转换和缺页中断,并用先进先出调度算法(FIFO)处理缺页中断;
2.要求:
① 指令序列的设定可以执行拟定,格式如表3;
② 在完成了FIFO换页策略后,可以选做LRU的换页策略,并进行比较;
③ 作业允许的页架数m在不同情况下的缺页中断率;
④ 程序运行时显示地址转变和页面调入调出过程。
3.步骤:
① 设计页表及其数据结构:
页号
标志:是否在主存;
页架号:设定页表在主存的位置;
修改标志:设定页面在主存中是否修改过;
磁盘上位置:设定页面在辅存中的位置;
例如:装入新页置换旧页时,若旧页在执行中没有被修改过,则不必将该页重写磁盘。因此,页表中增加是否修改过的标志,执行“存”指令和“写”指令时将对应的修改标志置成“1”表示修改过,否则为“0”表示未修改过。
表 1 页表格式
页号 标志 页架号 修改标志 在磁盘上位置





②设计一个地址转换程序半模拟硬件的地址转换和缺页中断。
当访问的页在主存时则形成绝对地址,但不去模拟指令的执行,可以输出转换后的绝对地址来表示一条指令已执行完成。当访问的页不在主存中时,则输出“*页号”来表示硬件产生了一次缺页中断。模拟地址转换流程见图1.1。
③ 设计FIFO页面调度程序;
FIFO页面调度算法总是先调出作业中最先进入主存中的哪一页。因此可以用一个数组来表示(或构成)页号队列。数据中每个元素是该作业已在主存中的页面号,假定分配给作业的页(架)数为m,且该作业开始的m页已装入主存,则数组可由m个元素构成。
P[0],P[1],P[2],…,P[m-1]
它们的初值为P[0]:=0,P[1]:=1,P[2]:=2,…,P[m-1]:=m-1
用一指针K指示当要调入新页时应调出的页在数组中的位置,K的初值为“0”,当产生缺页中断后,操作系统总是选择P[K]所指出的页面调出,然后执行。
④ 设计输入数据和输出格式;
如: 假定主存中页架大小为1024个字节,现有一个共7页的作业,其副本已在磁盘上。系统为该作业分配了4个页架,且该作业的第0页至第3页已装入内存,其作3页未主存,该作业的页表如下:

页号 标志 页架号 修改标志 在磁盘上位置
0 1 5 0 011
1 1 8 0 012
2 1 9 0 013
3 1 1 0 021
4 0 0 022
5 0 0 023
6 0 0 121
如果该作业依次执行的指令序列如附表3所示:
操作 页号 页内地址 操作 页号 页内地址
+ 0 070 移位 4 053
- 1 050 + 5 023
× 2 015 存 1 037
存 3 021 取 2 078
取 0 056 + 4 001
- 6 040 存 6 084
依次执行上述指令调试你所设计的程序(仅模拟指令的执行,不考虑序列中具体操作的执行)。
⑤ 编程上机,验证结果。
4.实验报告:
为进一步考察程序的执行,可自行确定若干组指令,运行程序,核对执行结果实验报告:
① 实验题目;
② 程序中所用的数据结构及说明;
③ 打印一份源程序并附上必要的说明;
④ 按照指令的执行序列,打印输出结果:绝对地址或调出、调入的页号。
P[K]:=要装入的新页页号
K:=(k+1)mod m
在实验中不必实际地启动磁盘执行调出一页和装入一页的工作,而用输出“OUT调出的页号”和“IN要装入的新页页号”来模拟一次调出和装入过程,模拟程序的流程图见附图1.1。

按流程控制过程如下:
提示:输入指令的页号和页内偏移和是否存指令 ,若d为-1则结束,否则进入流程控制过程,得P1和d,查表在主存时绝对地址P1×1024+d







...全文
189 1 点赞 打赏 收藏 举报
写回复
1 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
destory27 2017-11-20
#ifndef _PAGEM_H #define _PAGEM_H #include "FIFO.h" //enum EXISTS{NON_EXIST, EXIST}; //enum Update{Update_N, Update_Y}; typedef struct PMT{ unsigned char PageID; //页号 unsigned char F_EXISTS; //是否在主存 unsigned char PframeID; //页框号 unsigned char F_Update; //是否修改过 unsigned char DiskPosition; //磁盘位置 struct PMT *NEXT; //保存下一页面地址 }pmt; //指令 typedef struct AccQueue{ unsigned char PageID; //页号 unsigned int offset; //页内偏移量 unsigned char F_Instruction; //是否存指令 1:存 0:不存 -1:退出 struct AccQueue *next; unsigned char AccInfo[3]; //用于输出 unsigned char F_interrupt; //页面中断 }AccQue; typedef struct{ node *front; node *rear; }FIFO; pmt* SetPMT(void); void AccessQueue(pmt **P_page, FIFO **fifo, AccQue **structaccque, AccQue **accque); void PMTInfo(pmt ** P_page); FIFO* SetFIFO(pmt ** P_page); void Callingorder(pmt **P_page, FIFO **fifo, pmt **page); void Performance(AccQue **accque); #endif #include <stdio.h> #include <malloc.h> #include <stdio.h> #include <string.h> #include "PageM.h" const unsigned char M = 3; //主存容量 const unsigned char PageNum = 7; //该作业页面数 const unsigned int Msize = 1024; // pmt* SetPMT(void) { pmt *P_page = (pmt *)malloc(sizeof(pmt)); (pmt *)memset(P_page, 0x00, sizeof(pmt)); P_page->NEXT = NULL; for(int i = 0; i < PageNum; ++i) { pmt *P_npage = (pmt *)malloc(sizeof(pmt)); //建立页面 (pmt *)memset(P_npage, 0x00, sizeof(pmt)); P_npage->NEXT = NULL; P_npage->PageID = i; if(i < M) { P_npage->F_EXISTS = 1; P_npage->PframeID = (i | 0xA) + (i & 0xA) + ((i << 1) & 0xA) - 0X9; } else { P_npage->F_EXISTS = 0; P_npage->PframeID = -1; } P_npage->F_Update = 0; P_npage->DiskPosition = (i | 0xA) + (i & 0xA) + ((i << 1) & 0xA) + ((i << 1) | 0xA); pmt *page = P_page; while(page->NEXT) page = page->NEXT; page->NEXT = P_npage; page = NULL; } return P_page; } //访问 void AccessQueue(pmt **P_page, FIFO **fifo, AccQue **structaccque, AccQue **accque) { if(!P_page && !*P_page) fprintf(stderr, "P_page Error!\n"); if(!fifo && !*fifo) fprintf(stderr, "fifo Error!\n"); if(!structaccque && !*structaccque) fprintf(stderr, "structaccque Error!\n"); if(!accque && !*accque) fprintf(stderr, "accque Error!\n"); //遍历PMT表,查看访问页面是否在PMT表中 pmt *pagetmp = (*P_page)->NEXT; unsigned char Pflag = 0; //页面不在 while(pagetmp) { if(pagetmp->PageID == (*structaccque)->PageID) { Pflag = 1; //存指令 if(1 == (*structaccque)->F_Instruction) //是否更新 pagetmp->F_Update = 1; break; } pagetmp = pagetmp->NEXT; } if(!Pflag) { fprintf(stderr, "\t==>>没有该页面.\n"); return ; } //访问顺序保存到AccQue; /*AccQue *accque = (AccQue *)malloc(sizeof(AccQue)); //连接有效访问信息 (AccQue *)memset(accque, 0x00, sizeof(AccQue));*/ AccQue *acctmp = (*accque); while(acctmp->next) acctmp = acctmp->next; acctmp->next = (*structaccque); //将主存中的信息装入数组 node *Pageid = (*fifo)->front; unsigned char i = 0; while(Pageid != (*fifo)->rear->next) { (*accque)->AccInfo[i++] = Pageid->PageID; Pageid = Pageid->next; } if(i < 2) for(i; i <= 2; (*accque)->AccInfo[i++] = -1) ; //遍历队列 没有:需要调入 有:刷新 node *fifotmp = (*fifo)->front; unsigned char Fflag = 0; //不在队列中 while(fifotmp != (*fifo)->rear->next) { if(fifotmp->PageID == (*structaccque)->PageID) { Fflag = 1; (*structaccque)->F_interrupt = 0; //在队列 unsigned char i = 0; node *Pageidt = (*fifo)->front; while(Pageidt != (*fifo)->rear->next) { (*structaccque)->AccInfo[i++] = Pageidt->PageID; Pageidt = Pageidt->next; } if(i < 2) for(i; i <= 2; (*structaccque)->AccInfo[i++] = -1) ; break; } fifotmp = fifotmp->next; } if(!Fflag) //调入 { (*structaccque)->F_interrupt = 1; Callingorder(P_page, fifo, &pagetmp); node *Pageidtmp = (*fifo)->front; unsigned char i = 0; while(Pageidtmp != (*fifo)->rear->next) { (*structaccque)->AccInfo[i++] = Pageidtmp->PageID; Pageidtmp = Pageidtmp->next; } if(i < 2) for(i; i <= 2; (*structaccque)->AccInfo[i++] = -1) ; } else if(1 == Fflag) { fprintf(stderr, "\t==>>页面[%d]在主存中.", (*structaccque)->PageID); fprintf(stderr, "\t==>>地址: %d \n.", (*structaccque)->PageID * Msize + (*structaccque)->offset); } return; } void PMTInfo(pmt ** P_page) { if(!P_page || !*P_page) fprintf(stderr, "Error!"); fprintf(stderr, "\t+--------------------------------------------------------+\n"); fprintf(stderr, "\t| 页号 | 标志 | 页框号 | 修改标志 | 在磁盘位置 |\n"); fprintf(stderr, "\t+--------------------------------------------------------+\n"); pmt *pagetmp = *P_page; while(pagetmp->NEXT) { pmt *page = pagetmp->NEXT; fprintf(stderr, "\t| %d | %d |", page->PageID, page->F_EXISTS); if(255 == page->PframeID) fprintf(stderr, " "); else fprintf(stderr, " %2d ", page->PframeID); fprintf(stderr, "| %d | %2X |\n", page->F_Update, page->DiskPosition); //fprintf(stderr, "\t|--------------------------------------------------------|\n"); pagetmp = pagetmp->NEXT; // page = NULL; } fprintf(stderr, "\t+--------------------------------------------------------+\n"); return ; } #ifndef _FIFO_H #define _FIFO_H #include "PageM.h" typedef struct Node{ unsigned char PageID; //页号 struct Node *next; }node; #endif #include <stdio.h> #include <malloc.h> #include <string.h> #include "PageM.h" #include "FIFO.h" extern const unsigned char M; FIFO* SetFIFO(pmt ** P_page) { if(!P_page || !*P_page) fprintf(stderr, "Error!"); FIFO *fifo = (FIFO *)malloc(sizeof(FIFO)); (FIFO*)memset(fifo, 0x00, sizeof(FIFO)); fifo->front = (node *)malloc(sizeof(node)); (node *)memset(fifo->front, 0x00, sizeof(node)); fifo->front->next = NULL; fifo->rear = (node *)malloc(sizeof(node)); (node *)memset(fifo->rear, 0x00, sizeof(node)); fifo->rear = fifo->front; pmt *page = (*P_page)->NEXT; int capacity = 0; while(page && capacity++ < M) { node *P_node = (node *)malloc(sizeof(node)); (node *)memset(P_node, 0x00, sizeof(node)); P_node->PageID = page->PageID; P_node ->next = NULL; if(1 == capacity) fifo->front = P_node; fifo->rear->next = P_node; fifo->rear = P_node; page = page->NEXT; } return fifo; } //调入指令 void Callingorder(pmt **P_page, FIFO **fifo, pmt **page) { if(!page && !*page) fprintf(stderr, "Error!"); if(!fifo && !*fifo) fprintf(stderr, "Error!"); // 调出处理 pmt *pagetmp = (*P_page); while(pagetmp->NEXT) { if(pagetmp->NEXT->PageID == (*fifo)->front->PageID) { pagetmp->NEXT->F_EXISTS = 0; //设置不在主存 if(1 == pagetmp->NEXT->F_Update) { fprintf(stderr, "\t==>>页面[%d]的内容写回磁盘。\n", pagetmp->NEXT->PageID); pagetmp->NEXT->F_Update = 0; } //pagetmp->NEXT->PframeID = -1; fprintf(stderr, "\t==>>页面[%d]调出.\n", pagetmp->NEXT->PageID); break; } pagetmp = pagetmp->NEXT; } node *temp = (*fifo)->front; //队首 (*fifo)->front = (*fifo)->front->next; free(temp); node *P_node = (node *)malloc(sizeof(node)); (node *)memset(P_node, 0x00, sizeof(node)); P_node->PageID = (*page)->PageID; unsigned char i = (*page)->PageID; (*page)->PframeID = pagetmp->NEXT->PframeID; pagetmp->NEXT->PframeID = -1; (*page)->F_EXISTS = 1; P_node->next = NULL; (*fifo)->rear->next = P_node; (*fifo)->rear = P_node; fprintf(stderr, "\t==>>页面[%d]调入.\n", P_node->PageID); return ; } //FIFO性能分析 void Performance(AccQue **accque) { AccQue *acctmp = (*accque)->next; if(!acctmp) { fprintf(stderr, "\t==>>访问队列为空.\n"); return ; } fprintf(stderr, "\t+--------------------------------------------------------+\n"); fprintf(stderr, "\t| 时刻 |"); unsigned char time = 1; while(acctmp) { fprintf(stderr, " %d |", time++); acctmp = acctmp->next; } fprintf(stderr, "\n"); acctmp = (*accque)->next; fprintf(stderr, "\t| 页面走向 |"); while(acctmp) { fprintf(stderr, " %d |", acctmp->PageID); acctmp = acctmp->next; } fprintf(stderr, "\n"); acctmp = (*accque)->next; fprintf(stderr, "\t| |"); while(acctmp) { fprintf(stderr, " %d |", acctmp->AccInfo[2]); acctmp = acctmp->next; } fprintf(stderr, "\n"); fprintf(stderr, "\t| 主存容量 |"); acctmp = (*accque)->next; while(acctmp) { fprintf(stderr, " %d |", acctmp->AccInfo[1]); acctmp = acctmp->next; } fprintf(stderr, "\n"); fprintf(stderr, "\t| |"); acctmp = (*accque)->next; while(acctmp) { fprintf(stderr, " %d |", acctmp->AccInfo[0]); acctmp = acctmp->next; } fprintf(stderr, "\n"); unsigned char tmp = 0; fprintf(stderr, "\t| 缺页中断 |"); acctmp = (*accque)->next; while(acctmp) { fprintf(stderr, " %d |", acctmp->F_interrupt); acctmp = acctmp->next; } fprintf(stderr, "\n"); fprintf(stderr, "\t+--------------------------------------------------------+\n"); int rate = 0; acctmp = (*accque)->next; while(acctmp) { if(1 == acctmp->F_interrupt) ++rate; acctmp = acctmp->next; } fprintf(stderr, "\t 缺页率: %d / %d = %.2lf\n", rate , time-1, ((float)rate/(time-1))); return ; }
  • 打赏
  • 举报
回复
相关推荐
发帖
C语言
加入

6.5w+

社区成员

C语言相关问题讨论
申请成为版主
帖子事件
创建了帖子
2017-11-20 10:28
社区公告
暂无公告