1. 程式人生 > 其它 >實驗四 儲存器管理綜合實驗

實驗四 儲存器管理綜合實驗

實驗四 儲存器管理綜合實驗

實驗目的

  • 掌握LINUX中動態申請記憶體的方法;理解多工環境下儲存管理的重要性以及基本儲存管理實現方法;
  • 理解虛擬儲存管理實現基本原理以及頁面淘汰演算法對虛擬儲存器效能影響及頁面淘汰演算法的實現。

實驗工具及環境

  • LINUX系統網路環境或單機,gcc編譯器。Windows系統網路環境+遠端SSH客戶端軟體。

實驗內容

  • (1)編寫一個程式申請兩塊大小為10的記憶體,分別存放字串“123456789”和“987654321”,並輸出字串及存放地址,然後重新調整記憶體大小為20,再次輸出地址。使用鍵盤命令檢視程式執行前後的記憶體使用情況。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <malloc.h> 
int main(void)
{
	char *str;
	if (str = (char *)malloc(10 * sizeof(char)))  /*申請大小為10的記憶體*/
	{
		printf("Not enough memory to allocate buffer\n");
		exit(1);
	}
	strcpy(str,"123456789");
	printf("String is %s\n %p\n",str,str);
	if(str = (char *)malloc(20 * sizeof(char)))   /*重新調整記憶體大小為20*/
	{
		printf("Not enough memory to reallocate buffer\n");
		exit(1);
	}
        strcpy(str,"987654321");
	printf("String is %s\n %p\n",str,str);
	free(str);
	return(0);
}
  • (2)利用C語言,程式設計實現先進先出、OPT、LRU中的一個演算法,開發一個虛擬儲存器的模擬程式,實現虛擬儲存器的頁面排程,頁面序列從指定的陣列或文字檔案(TXT檔案)中取出;輸出:頁面排程順序,記憶體物理塊中頁面變化情況,缺頁的總次數和缺頁率。
#include<stdio.h> 
#define M 4 
#define N 17 
#define Myprintf printf("|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|\n")	// 表格控制
typedef struct page 
{ 
	int num;	// 記錄頁面號
	int time;	// 記錄調入記憶體時間
}Page;			// 頁面邏輯結構,結構為方便演算法實現設計
  
Page b[M];		// 記憶體單元數 
int c[M][N];	// 暫儲存記憶體當前的狀態:緩衝區 
int queue[100];	// 記錄調入佇列
int K;		// 調入佇列計數變數 
  
// 初始化記憶體單元、緩衝區 
void Init(Page *b,int c[M][N]) 
{ 
	int i,j; 
	for(i=0;i<N;i++) 
	{ 
		b[i].num=-1;   // 初始化記憶體單元
		b[i].time=N-i-1; 
	} 
	for(i=0;i<M;i++) 
		for(j=0;j<N;j++) 
			c[i][j]=-1;    // 初始化緩衝區
} 
  
// 取得在記憶體中停留最久的頁面,預設狀態下為最早調入的頁面
int GetMax(Page *b) 
{ 
	int i; 
	int max=-1; 
	int tag=0; 
	for(i=0;i<M;i++) 
	{ 
		if(b[i].time>max) 
		{ 
			max=b[i].time; 
			tag=i; 
		} 
	} 
	return tag; 
} 
  
// 判斷頁面是否已在記憶體中 
int	Equation(int fold,Page *b) 
{ 
	int i; 
	for(i=0;i<M;i++) 
	{ 
		if (fold==b[i].num) 
			return i; 
	} 
	return -1; 
} 
// LRU核心部分
void Lru(int fold,Page *b) 
{ 
	int i; 
	int val; 
	val=Equation(fold,b); 
	if (val>=0) 
	{ 
		b[val].time=0; 
		for(i=0;i<M;i++) 
			if (i!=val) 
				b[i].time++; 
	} 
	else 
	{ 
		queue[++K]=fold;   // 記錄調入頁面
		val=GetMax(b);     //取得在記憶體中停留最久的頁面 
		b[val].num=fold; 
		b[val].time=0; 
		for(i=0;i<M;i++) 
			if (i!=val) 
				b[i].time++; 
	} 
} 
  
// 主程式
void main() 
{ 
	int a[N]={1,0,1,0,2,4,1,0,0,8,7,5,4,3,2,3,4}; 
	int i,j; 
  
start: 
	K=-1; 
	Init(b, c); 
	for(i=0;i<N;i++) 
	{ 
		Lru(a[i],b); 
		c[0][i]=a[i]; 
		// 記錄當前的記憶體單元中的頁面 
		for(j=0;j<M;j++) 
			c[j][i]=b[j].num; 
	} 
	// 結果輸出
	printf("記憶體狀態為:\n"); 
	Myprintf; 
	for(j=0;j<N;j++) 
		printf("|%2d ",a[j]); 
	printf("|\n"); 
	Myprintf; 
	for(i=0;i<M;i++) 
	{	for(j=0;j<N;j++) 
		{ 
		if(c[i][j]==-1) 
			printf("|%2c ",32); 
		else 
			printf("|%2d ",c[i][j]); 
		} 
		printf("|\n"); 
	} 
	Myprintf; 
	printf("\n調入佇列為:"); 
	for(i=0;i<K+1;i++) 
		printf("%3d",queue[i]); 
	printf("\n缺頁次數為:%6d\n缺頁率:%16.6f",K+1,(float)(K+1)/N); 
	printf("\nAre you continuing!\ty?"); 
        system("stty echo");
	if(getchar()=='y') 
		goto start; 
} 
  • (3)選做:利用C語言,實現儲存分配演算法,開發一個儲存管理的模擬程式,對記憶體空間的管理和分配。記憶體空間的管理採用分割槽管理方式。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define total_page_address 640  // 作業的地址流數
#define total_page 32  // 作業的頁面數
int page[total_page_address];
void FIFO(int mem_frame);
void LRU(int mem_frame);
void OPT(int mem_frame);
main()
{
	int i,p,fl;
	srand(getpid()); // 設定隨機種子
	// 產生頁地址流,假設有50%的指令是順序執行的
	for (i=0;i<total_page_address;i++)
		page[i]=-1;
	for (i=0;i<total_page_address;i+=2)
	{  
		fl=0;
		while (fl==0)
		{
			p=rand()%total_page_address;
			if (page[p]==-1)	fl=1;
		}
		page[p]=rand()%total_page; 
	}
	p=0;
	for (i=0;i<total_page_address;i++)
	{
		if (page[i]==-1)
            page[i]=p;
		else 
		    p=page[i];
	}
	for (i=4;i<=32;i++) // 使用者記憶體工作區從4 個頁面到32 個頁面
	{
		printf("%2d page frames  ",i);
		FIFO(i);   // 呼叫FIFO
		LRU(i);   // 呼叫LRU 
		OPT(i);   // 呼叫OPT
		printf("\n");
	}
}

void FIFO(int mem_frame)
{
	int page_message[100],i,ptr=0,j; 
	int invalid=0,exist;
	// page_message 存放頁面資訊,ptr指向最早進入的頁面
	for (i=0;i<100;i++) page_message[i]=-1;  // -1表示無頁面
	for (i=0;i<total_page_address;i++)
	{
		//查詢該頁是否在記憶體
		exist=0;
		for (j=0;j<mem_frame;j++)
			if (page_message[j]==page[i])
				exist=1; //該頁在記憶體中
		if (exist==0) //該頁不在記憶體中,失敗
		{
			invalid++;
			for (j=0;j<mem_frame;j++)
				if (j==mem_frame) //是否有空閒記憶體塊
				{
					page_message[j]=page[i]; //如果有裝入對應的頁面
					break;
				}
			if (j>=mem_frame)
			{
				page_message[ptr]=page[i]; //淘汰最早進入的頁面
				ptr=(ptr+1) % mem_frame;
			}
		}
	}
	printf("FIFO: %6.4f  ",1-(float)invalid/total_page_address);
}

void LRU(int mem_frame)
{
	int page_message[100],i,ptr=0,j,m,n; 
	int invalid=0,exist,sit1,sit2;
	// page_message 存放頁面資訊,ptr指向最早進入的頁面
	for (i=0;i<100;i++) page_message[i]=-1;  // -1表示無頁面
	for (i=0;i<total_page_address;i++)
	{
		//查詢該頁是否在記憶體
		exist=0;
		for (j=0;j<mem_frame;j++)
			if (page_message[j]==page[i])
				exist=1; //該頁在記憶體中
		if (exist==0) //該頁不在記憶體中,失敗
		{
			invalid++;
			for (j=0;j<mem_frame;j++)
				if (page_message[j]==-1) //是否有空閒記憶體塊
				{
					page_message[j]=page[i]; //如果有裝入對應的頁面
					break;
				}
			if (j>=mem_frame)
			{
				//查詢最久未用頁面進行淘汰
                exist=3333;
				for (m=0;m<mem_frame;m++)
				{
					for(n=i-1;n>=0;n--)
						if(page_message[m]==page[n]) {
							sit1=n;
							break;
						}
					if (exist>sit1) {
						exist=sit1;
						sit2=m;
					}
				}
				page_message[sit2]=page[i];				
			}
		}
	}
	printf("LRU: %6.4f  ",1-(float)invalid/total_page_address);
}

void OPT(int mem_frame)
{
	int page_message[100],i,ptr=0,j,m,n; 
	int invalid=0,exist,sit1,sit2;
	// page_message 存放頁面資訊,ptr指向最早進入的頁面
	for (i=0;i<100;i++) page_message[i]=-1;  // -1表示無頁面
	for (i=0;i<total_page_address;i++)
	{
		//查詢該頁是否在記憶體
		exist=0;
		for (j=0;j<mem_frame;j++)
			if (page_message[j]==page[i])
				exist=1; //該頁在記憶體中
		if (exist==0) //該頁不在記憶體中,失敗
		{
			invalid++;
			for (j=0;j<mem_frame;j++)
				if (page_message[j]==-1) //是否有空閒記憶體塊
				{
					page_message[j]=page[i]; //如果有裝入對應的頁面
					break;
				}
			if (j>=mem_frame)
			{
				//查詢最久未用頁面進行淘汰
                exist=-1;
				for (m=0;m<mem_frame;m++)
				{
					for(n=i+1;n<total_page_address;n++)
						if(page_message[m]==page[n]) {
							sit1=n;
							break;
						}
					if (n>=total_page_address)
						sit2=m;
					else
						if (exist<sit1) {
							exist=sit1;
							sit2=m;
						}
				}
				page_message[sit2]=page[i];				
			}
		}
	}
	printf("LRU: %6.4f  ",1-(float)invalid/total_page_address);
}