操作系統 實驗二 請求分頁存儲器管理

實驗目的:

實現分頁式存儲地址轉換過程,在此基礎上實現請求分頁的地址轉換。實現請求分頁式地址轉換中出現的缺頁現象中,用到的FIFO、LRU、OPT置換算法。


實現方法:

用一張位示圖,來模擬內存的分配情況,利用隨機數產生一組0和1的數對應內存的使用情況。

利用結構體數組將頁表和內存塊封裝。


實現過程:

#include<stdio.h>
#include<stdlib.h>
#include<iostream.h>
#include<time.h>
struct Page
{
	int kuai;
	int stage;
}FPage[1000],LPage[1000];

struct Memory
{
	int num;
	int page;
}FMemory[1000],LMemory[1000],OMemory[1000];

int PageLength;			/*頁表長度*/
int Memsize;			/*內存塊數*/
int FAbsent,LAbsent,OAbsent,visit;			/*FIFO中的缺頁次數	LRU中的缺頁次數		訪問內存次數	*/
int Logical;			/*邏輯地址*/
int Pagenumber,Pageaddr;/*頁號	頁內地址*/
int Physical;		/*物理地址*/
int PageSize;		/*塊的大小*/
int Freemem;		/*空閒內存*/

int G[8][8];

int opt[10000];		int oth=0;
int temp[1000];

void GShow()
{
	int i,j;
	printf("位式圖:\n");
	for(i=0;i<8;i++)
	{
		printf("\t");
		for(j=0;j<8;j++)		
			printf("%d ",G[i][j]);
		printf("\n");
	}
}


void init()					/*初始化*/
{
	srand((unsigned)time(NULL));
	int i,j;
	for(i=0;i<8;i++)
		G[0][i]=1;
	for(i=1;i<8;i++)
	{
		for(j=0;j<8;j++)
			G[i][j]=rand()%2;
	}	
	
	for(i=0;i<PageLength;i++)
	{
		FPage[i].kuai=-1;		FPage[i].stage=0;	
		LPage[i].kuai=-1;		LPage[i].stage=0;
	}
	for(i=0;i<Memsize;i++)
	{
		FMemory[i].page=-1;
	}
	for(i=0;i<Memsize;i++)
	{
		LMemory[i].page=-1;
	}	
	for(i=0;i<Memsize;i++)
	{
		OMemory[i].num=i;
		OMemory[i].page=-1;
	}
	
	FAbsent=LAbsent=visit=0;
}


void Show()
{
	int i;
	
	printf("FPage:\t\t\t\t\tLPage:\n");
	printf("\t頁號\t塊號\t狀態位\t\t\t頁號\t塊號\t狀態位\n");
	for(i=0;i<PageLength;i++)
	{
		printf("\t%d\t",i);		
		if(FPage[i].kuai==-1)
			printf(" \t");
		else
			printf("%d\t",FPage[i].kuai);
		printf("%d",FPage[i].stage);
		printf("\t\t\t%d\t",i);
		if(LPage[i].kuai==-1)
			printf(" \t");
		else
			printf("%d\t",LPage[i].kuai);
		printf("%d\n",LPage[i].stage);
	}
	printf("\nFMemory:\t\t\t\tLMemory:\n");
	printf("\t塊號\t頁號\t\t\t\t塊號\t\t頁號\n");
	for(i=Memsize-1;i>=0;i--)
	{
		printf("\t%d\t",i);
		if(FMemory[i].page==-1)
			printf(" \t\t");
		else
			printf("%d\t\t",FMemory[i].page);
		printf("\t\t%d\t",i);
		if(LMemory[i].page==-1)
			printf("\n");
		else
			printf("\t%d\n",LMemory[i].page);
	}
	printf("Logical: %d\n",Logical);
	printf("Count: %d	%d\n",Pagenumber,Pageaddr);
	printf("Physical: %d\n",Physical);
	printf("PageSize: %d\n",PageSize);
	printf("Visit: %d\n",visit);
	printf("FAbsent: %d		LAbsent: %d\n",FAbsent,LAbsent);
	printf("FRate: %.2f%%		LRate: %.2f%%\n",(double)FAbsent*100/(double)visit,(double)LAbsent*100/(double)visit);
}


void FIFO()				/*FIFO算法*/
{
	int i;
	int m,n;
	
	
	if(FPage[Pagenumber].stage==1)		/*命中*/
		;
	else				/*缺頁*/
	{
		FAbsent++;
		FPage[Pagenumber].stage=1;
		
		for(i=0;i<Memsize;i++)
		{
			if(FMemory[i].page==-1)
			{
				for(m=1;m<8;m++)
				{
					for(n=0;n<8;n++)
						if(G[m][n]==0)
						{
							break;
						}
						if(n<8)
							break;
				}
				Freemem=(m-1)*8+n;
				FMemory[i].page=Pagenumber;
				FPage[Pagenumber].kuai=Freemem;
				
				break;
			}
		}
		if(i==Memsize)
		{
			FPage[Pagenumber].kuai=FPage[FMemory[0].page].kuai;
			FPage[FMemory[0].page].kuai=-1;
			FPage[FMemory[0].page].stage=0;
			for(i=0;i<Memsize-1;i++)
				FMemory[i].page=FMemory[i+1].page;
			FMemory[i].page=Pagenumber;
		}
	}
	
}
void LRU()					/*LRU算法*/
{
	int i,j,m,n,l;

	//bool flag=true;
	
	for(l=0;l<Memsize;l++)
		if(LMemory[l].page==-1)
			break;
	
	if(LPage[Pagenumber].stage==1)/*命中*/
	{
		for(i=0;i<l;i++)
		{
			if(LMemory[i].page==Pagenumber)
			{
				for(j=i;j<l-1;j++)
				{
					LMemory[j].page=LMemory[j+1].page;
				}
				LMemory[j].page=Pagenumber;
				break;
			}
		}
	}
	else			/*沒命中*/
	{
		LAbsent++;
		LPage[Pagenumber].stage=1;

		if(l<Memsize)		//問題出在這裏,l++之前需要判斷一下 如果l<memsize說明有空閒塊,則l++ ,否則塊已經滿了,l不能++ ... 
			l++;
		for(i=0;i<l;i++)
		{
			if(LMemory[i].page==-1)
			{
				for(m=1;m<8;m++)
				{
					for(n=0;n<8;n++)
						if(G[m][n]==0)
						{
							G[m][n]=1;
							break;
						}
						if(n<8)
							break;
				}
				Freemem=(m-1)*8+n;
				LMemory[i].page=Pagenumber;
				LPage[Pagenumber].kuai=Freemem;
				for(j=i;j<l-1;j++)
				{
					LMemory[j].page=LMemory[j+1].page;
				}
				LMemory[j].page=Pagenumber;
				break;
			}
		}
		if(i==l)
		{
			LPage[LMemory[0].page].stage=0;
			LPage[Pagenumber].kuai=LPage[LMemory[0].page].kuai;
			LPage[LMemory[0].page].kuai=-1;
			for(j=0;j<l-1;j++)
				LMemory[j].page=LMemory[j+1].page;
			LMemory[j].page=Pagenumber;
		}
	}
}

void OPTshow()
{
	int i;
	printf("\t");
	for(i=Memsize-1;i>=0;i--)
	{
		if(OMemory[i].page==-1)
			printf("  ");
		else
			printf(" %d",OMemory[i].page);
	}
	printf("\n");
}

void OPT()
{
	printf("\nOPTMemory:\n");
	printf("\t 2 1 0\n\n");
	int i,j,k,l,m,n;
	int count=0;
	for(i=0;i<oth;i++)
	{
		for(j=0;j<Memsize;j++)
		{
			if(OMemory[j].page==opt[i])
				break;
		}
		if(j<Memsize)
			;
		else
		{
			for(j=0;j<Memsize;j++)
			{
				if(OMemory[j].page==-1)			/*如果此時內存沒滿還有空缺 就直接將頁號寫進去*/
				{
					OMemory[j].page=opt[i];
					break;
				}
			}
			if(j==Memsize)				/*需要發生置換*/
			{
				OAbsent++;
				for(n=0;n<Memsize;n++)
					temp[n]=0;	
				
				for(k=i+1;k<oth;k++)
				{	
					for(l=0;l<Memsize;l++)
					{
						if(OMemory[l].page==opt[k])
						{
							temp[l]++;
							break;
						}
					}
					count=0;
					for(m=0;m<Memsize;m++)
					{
						if(temp[m]==0)
							count++;
					}
					if(count>1&&k<oth-1)
						;
					else
					{
						for(m=0;m<Memsize;m++)
							if(temp[m]==0)
							{
								OMemory[m].page=opt[i];
								break;
							}
					}
				}
			}
		}
		OPTshow();		
	}
	printf("OAbsent: %d\n",OAbsent);
	printf("ORate: %.2f%%\n",(double)OAbsent*100/(double)visit);
	
}

void cometrue()
{
	printf("輸入頁表長度(頁):");
	scanf("%d",&PageLength);
	printf("輸入內存塊數(塊):");
	scanf("%d",&Memsize);
	printf("輸入頁面大小(kb):");
	scanf("%d",&PageSize);
	init();
	while(printf("輸入邏輯地址(10進制): ")&&scanf("%d",&Logical))
	{
		if(Logical!=-1)
		{
			Pagenumber=Logical/(PageSize*1024);
			Pageaddr=Logical%(PageSize*1024);
			if(Pagenumber>=PageLength)
			{
				printf("越界中斷......!\n");
				continue;
			}
			opt[oth++]=Pagenumber;
			GShow();
			FIFO();
			LRU();
			
			Physical=Freemem*PageSize*1024+Pageaddr;
			visit++;
			
			Show();
		}
		else if(Logical==-1)
		{
			int i;
			printf("頁號訪問序列:\n");
			for(i=0;i<oth;i++)
				printf("%d  ",opt[i]);
			printf("\n");
			OPT();
			break;
		}
	}
}

int main()
{
	cometrue();
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章