【操作系统实验 / C++】在分页管理方式下采用位示图来表示主存分配情况,实现主存分配和回收(附代码)

1、选题及题目要求

在分页管理方式下采用位示图来表示主存分配情况,实现主存分配和回收
(1) 假定系统的主存被分成大小相等的64个块,用0/1对应空闲/占用。
(2) 当要装入一个作业时,根据作业对主存的需求量,先查空闲块数是否能满足作业要求,若能满足,则查位示图,修改位示图和空闲块数。位置与块号的对应关系为:

块号 = j * 8 + i,其中 i 表示位,j 表示字节。
根据分配的块号建立页表。页表包括两项:页号和块号。

(3) 回收时,修改位示图和空闲块数。
要求能接受来自键盘的空间申请及释放请求,能显示位示图和空闲块数的变化,能显示进程的页表。

2、数据结构设计

根据题目要求,分别设置了两组结构,用于存储位示图和作业。

struct BitMap       //用于存储位示图   
{  
    int map[8][8];  //8*8=64,位示图   
    int free;       //剩余的空闲块数   
}bitmap;  
 
typedef struct process      //用于存储作业   
{  
	int num;                //作业序号   
	int size;               //作业大小   
	int *pagetable;         //页表   
	struct process *next;   //下一作业   
	struct process *pre;    //上一作业   
}process; 
  • 其中位示图采用全局数组储存,0代表空闲,1代表占用。作业采用指针结构储存,使用队列的形式储存和释放,每输入一个新的作业,将其作为头指针插入队列,删除时则遍历队列,找到对应作业并删除。
  • 同时,在作业中设立一个不定项的数组指针,用于存储页表,在输入作业的大小后,创建一个相应大小的数组,并按序存储内存块号,同时修改位示图。删除时,也通过读取页表来修改位示图。

3、程序主要思路和原理

主要思路:

  • 针对作业,采用队列结构连接链表,其中头指针置为空,每输入一个新作业时,将其作为头指针的下一指针前插入链表,将下一作业的上一指针置为当前作业,同时当前作业的下一指针置为下一作业。剔除时同理,首先遍历链表,找到所有符合条件(即进程号为输入值)的进程,并依次修改当前指针的前指针和后指针。采用双指针结构避免出现数据错误。
  • 针对内存和位示图,每输入一个新作业时,首先检查当前是否有足够的内存块使用,如果有则修改位示图和free数据,并且产生相应的页表。释放作业时,也修改位示图和free数据。

原理:链表,头插法队列,指针,全局数组

4、程序运行结果

  • 运行程序,出现如下图所示的程序菜单。

在这里插入图片描述

  • 选择1操作,创建一个新作业并输入作业序号、作业大小,随后装入作业并生成页表,如下图所示。

在这里插入图片描述

  • 随机创建几个新作业,随后回收其中序号2的作业,如下图所示。

在这里插入图片描述

  • 此时查看位示图,如下图所示。
    在这里插入图片描述
  • 选择展示序号为23的作业页表,结果如下图所示。
    在这里插入图片描述

可见,未出现程序错误,且程序运行结果正常,该实验完成。

5、详细代码

#include <iostream>
#include <stdio.h>
using namespace std;

struct BitMap		//用于存储位示图 
{
	int map[8][8];	//8*8=64,位示图 
	int free;		//剩余的空闲块数 
}bitmap;

typedef struct process		//用于存储作业 
{
	int num;				//作业序号 
	int size;				//作业大小 
	int *pagetable;			//页表 
	struct process *next;	//下一作业 
	struct process *pre;	//上一作业 
}process;


void SetProcess(process *head)		//创立作业,生成页表 
{
	int setnum;
	int i=0,j=0,k=0,finish=0;
	process *temp = new process();
	cout<<endl<<"请输入作业序号(数字且不为0):";
	cin>>setnum;
	
	if(setnum == 0)
	{
		cout<<endl<<"错误!不能创建0号作业,返回。";
		delete temp;
		return;
	}
	
	temp->num = setnum;
	cout<<endl<<"请输入作业大小(<=64):";
	cin>>temp->size;
	
	if(temp->size > bitmap.free)		//判断现有空间是否足够分配 
	{
		cout<<endl<<"当前内存没有足够的空间分配,返回。";
		delete temp;
		return;
	}
	
	temp->next = head->next;	//头插法插入新作业 
	if(head->next != NULL)
		head->next->pre = temp;
	temp->pre = head;
	head->next = temp;
	
	temp->pagetable = new int [temp->size];	//创立页表数组 
	for(i=0; i<8 && finish == 0; i++)
	{
		for(j=0; j<8 && finish == 0; j++)
		{
			if(bitmap.map[i][j] == 0)		//修改页表数据 
			{
				bitmap.map[i][j] = 1;
				bitmap.free --;
				temp->pagetable[k] = 8*i + j;
				k++;
			}
			
			if(k == temp->size)		//用于结束循环 
				finish = 1;
		}
	} 
	
	cout<<endl<<"已装入作业,页表如下:"<<endl<<"页号\t";		//输出页表 
	k = temp->size;
	for(i=0; i<k; i++)
	{
		cout<<i+1<<'\t';
	}
	cout<<endl<<"块号\t";
	for(j=0; j<k; j++)
	{
		cout<<temp->pagetable[j]<<'\t';
	}
}


void RecProcess(process *head)		//回收作业,退还内存 
{
	int recnum;
	int i=0,j=0,k=0,l=0,found=0;
	process *temp = new process();
	cout<<endl<<"请输入回收作业序号(数字且不为0):";
	cin>>recnum;
	
	if(recnum == 0)
	{
		cout<<endl<<"错误!不能删除0号作业,返回。";
		return;
	}
	
	for(temp=head; temp != NULL; temp = temp->next)		//找到进程 
	{
		if(temp->num == recnum)
		{
			found = 1;
			k = temp->size;
			for(l=0; l<k; l++)		//删除数据 
			{
				i = temp->pagetable[l] / 8;
				j = temp->pagetable[l] % 8;
				bitmap.map[i][j] = 0;
				bitmap.free ++;
			}
			
			if(temp->pre != NULL)		//不允许删除头结点 
			{
				if(temp->next != NULL)		//不是尾结点 
				{
					temp->pre->next = temp->next;
					temp->next->pre = temp->pre;
					delete temp;
				}
				
				else						//是尾结点 
				{
					temp->pre->next = NULL;
					delete temp;
				}
			}
			
			cout<<endl<<"已找到并回收序号为"<<recnum<<"的作业。";
			cout<<endl<<"该作业大小为"<<k<<"。"<<endl;
			continue;
		}
	}
	
	if(found == 0)		//未找到进程 
	{
		cout<<endl<<"未找到该作业,返回。";
		return;
	}
	
	cout<<endl<<"完成回收,返回。";
	return;
}


void ShowBitMap()		//展示位示图 
{
	cout<<endl<<"当前位示图状态如下:"<<endl;
	cout<<'\t'<<"0\t"<<"1\t"<<"2\t"<<"3\t"<<"4\t"<<"5\t"<<"6\t"<<"7\t";
	cout<<endl<<"****";
	 
	int i=0,j=0;
	for(i=0; i<8; i++)
	{
		cout<<endl<<i<<'\t';
		for(j=0; j<8; j++)
		{
			cout<<bitmap.map[i][j]<<'\t';
		}
	}
	
	cout<<endl<<endl<<"完成位示图展示,返回。";
}


void ShowPageTable(process *head)		//展示页表 
{
	int shownum;
	int i=0,j=0,k=0,l=0,found=0;
	process *temp = new process();
	cout<<endl<<"请输入查看作业序号(数字且不为0):";
	cin>>shownum;
	
	if(shownum == 0)
	{
		cout<<endl<<"错误!不能查看0号作业,返回。";
		return;
	}
	
	for(temp=head; temp != NULL; temp = temp->next)		//找到进程 
	{
		if(temp->num == shownum)
		{
			found = 1; 
			cout<<endl<<"序号为"<<shownum<<"的作业页表如下:"<<endl<<"页号\t";		//输出页表 
			k = temp->size;
			for(i=0; i<k; i++)
			{
				cout<<i+1<<'\t';
			}
			cout<<endl<<"块号\t";
			for(j=0; j<k; j++)
			{
				cout<<temp->pagetable[j]<<'\t';
			}
			
			cout<<endl<<"已找到并展示序号为"<<shownum<<"的作业页表。";
			cout<<endl<<"该作业大小为"<<k<<"。"<<endl;
			continue;
		}
	}
	
	if(found == 0)		//未找到进程 
	{
		cout<<endl<<"未找到该作业,返回。";
		return;
	}
	
	cout<<endl<<"完成作业页表展示,返回。"; 
}


int main()
{
	char choice;
	bitmap.map[8][8] = 0;
	bitmap.free = 64;
	
	process *head = new process();
	head->next = NULL;
	head->pre = NULL;
	head->num = 0;
	
	do
	{
		cout<<endl; 
		cout<<endl<<"-----------操作列表-----------";
		cout<<endl<<"------------------------------";
		cout<<endl<<"0.退出程序;";
		cout<<endl<<"1.创建新作业,并请求内存空间;";
		cout<<endl<<"2.回收作业,并返回内存;";
		cout<<endl<<"3.展示位示图;";
		cout<<endl<<"4.展示进程页表;";
		cout<<endl<<"5.清空屏幕。";
		cout<<endl<<"------------------------------"; 
		cout<<endl<<"**请选择您要进行的操作:";
		
		cin>>choice;
		
		switch(choice)
		{
			case '1':
				SetProcess(head);
				break;
			case '2':
				RecProcess(head);
				break;
			case '3':
				ShowBitMap();
				break;
			case '4':
				ShowPageTable(head);
				break;
			case '5':
				system("cls");
				break;
			default:
				cout<<endl<<"输入错误!请重新输入!"; 
		}
	}while(choice != '0');
	
	return 0;
}

注:水平较菜,可能存在代码不简洁的部分,但是代码实测是可以跑的,仅供思路参考~

  • 7
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值