操作系统原理与实验——实验八连续存储管理方式的模拟与实现(可变分区)

实验指南

1.本实验是模拟存储管理方式中的可变分区分配与回收算法,系统需要建立两张分区表,分别是未(已)分配分区表,然后根据待装入作业的名称和大小到未分配分区列表中查找(具体包含最先/最优/最坏适配算法)满足要求的空闲分区,再将该分区一分为二,前半部分分配给作业使用并登记到已分配分区表的空栏中,剩余部分仍修改为新的空闲分区,最后通过动态重定位方式完成地址转换;当作业运行结束时,根据该作业名查找已分配分区表,找到与作业名相同的分区,然后将该分配从已分配分区表中删除,最后按照无上邻无下邻、有上邻无下邻、无上邻有下邻和有上邻有下邻四种形式分别修改未分配分区表。

 

测试用例:

样例一:

最先分配算法

256
40
1
1
JOB_A
15
1
1
JOB_B
50
1
1
JOB_C
10
1
1
JOB_D
25
1
1
JOB_E
14
2
JOB_B
2
JOB_D
1
1
JOB_F
32
2
JOB_C
2
JOB_E
2
JOB_A
2
JOB_F

 

样例二:

最优分配算法

256
40
1
2
JOB_A
15
1
2
JOB_B
50
1
2
JOB_C
10
1
2
JOB_D
5
1
2
JOB_E
14
2
JOB_D
1
2
JOB_H
6

关键代码

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<malloc.h>
#include<string.h>
using namespace std;
//内存结构体
typedef struct memory_node
{    
	int size; //内存大小
    int address; //内存始址
} memoryNode;
memoryNode memory;
//分区结构体
typedef struct link_node
{    	
	int size;//分区大小
    int address; //分区始址
    char flag[20]; //分区状态,空闲或者占用作业名
    struct link_node *next;
} node;
//作业结构体
typedef struct job_node
{    
	int id;//作业编号
    char name[20];//作业名
    int size;//作业大小
} job;
void print(node *yfp,node *wfp)
{
		printf("\n*******************主存分配情况**************");
		printf("\n已分配:"); 
		
		int count = 1;
		node *dy;
		dy=yfp->next;
		printf("\n分区号   大小(KB)   起始(KB)   状态");
		while(dy!=NULL)
		{
			printf("\n%d\t  %d\t\t %d\t   ",count,dy->size,dy->address);
			if(dy->flag[0] == '\0')
			printf("空闲");
			else
			printf("%s",dy->flag);
			dy = dy->next;
			count++;
		}
	
		printf("\n未分配:");
		dy=wfp->next;
		printf("\n分区号   大小(KB)   起始(KB)   状态");
		while(dy!=NULL)
		{
			printf("\n%d\t  %d\t\t%d\t   ",count,dy->size,dy->address);
			if(dy->flag[0] == '\0')
			printf("空闲");
			else
			printf("%s",dy->flag);
			dy = dy->next;
			count++;
		}
}
void govern(node *yfp,node *wfp)
{
	int option; 
	printf("\n*****************分配算法*****************"); 
	printf("\n        *       1.最先分配算法       *");
	printf("\n        *       2.最优分配算法       *");
	printf("\n        *       3.最坏分配算法       *");
	printf("\n                请输入选项:"); 
	scanf("%d",&option);
	if(option == 1)//最先分配算法
	{
		job JOB;
		printf("\n请输入作业名:");
		scanf("%s",&JOB.name);
		printf("\n%s需要分配的主存大小(单位:KB):",JOB.name);
		scanf("%d",&JOB.size); 
		node*p = wfp->next;
		while(p != NULL)
		{
			if(p->size >= JOB.size)
			{
				break;
			}
			p = p->next; 
		}
		node*NODE = (node*)malloc(sizeof(node));//创建节点插入已分配表中 
		NODE->next = NULL;
		NODE->size = JOB.size;
		NODE->address = p->address;
		int i=0;
		for(i=0;i<strlen(JOB.name);i++)
		{
			NODE->flag[i] = JOB.name[i];
		} 
		NODE->flag[i+1]='\0';
		 
		
		node*h = yfp;//修改已分配表 
		while(h->next != NULL)
		{
			h = h->next; 
		}
		h->next = NODE;
		
		node*hh = wfp->next;
		node*pre = wfp;
		while(hh != p)
		{
			pre=hh;
			hh = hh->next;
		}
		if(p->size == JOB.size)
		{
			pre->next = p->next;
		}
		else
		{
			p->address = p->address + JOB.size;
			p->size = p->size -JOB.size;
		}
		printf("\n分配成功!");
		print(yfp,wfp);
	}
	else if(option == 2)//最优分配算法
	{
		job JOB;
		printf("\n请输入作业名:");
		scanf("%s",&JOB.name);
		printf("\n%s需要分配的主存大小(单位:KB):",JOB.name);
		scanf("%d",&JOB.size); 
		node*p = wfp->next,*best = NULL;
		while(p != NULL)
		{
			if(p->size >= JOB.size && best == NULL)
			{
				best = p;
			}
			if(p->size >= JOB.size && p->size <best->size)
			{
				best = p;
			}
			p = p->next; 
		}
		node*NODE = (node*)malloc(sizeof(node));//创建节点插入已分配表中 
		NODE->next = NULL;
		NODE->size = JOB.size;
		NODE->address = best->address;
		int i=0;
		for(i=0;i<strlen(JOB.name);i++)
		{
			NODE->flag[i] = JOB.name[i];
		} 
		NODE->flag[i+1]='\0';
		 
		
		node*h = yfp;//修改已分配表 
		while(h->next != NULL)
		{
			h = h->next; 
		}
		h->next = NODE;
		
		node*hh = wfp->next;
		node*pre = wfp;
		while(hh != best)//修改未分配表 
		{
			pre=hh;
			hh = hh->next;
		}
		if(best->size == JOB.size)
		{
			pre->next = best->next;
		}
		else
		{
			best->address = best->address + JOB.size;
			best->size = best->size -JOB.size;
		}
		printf("\n分配成功!");
		print(yfp,wfp);
	}
	else//最坏分配算法
	{
		job JOB;
		printf("\n请输入作业名:");
		scanf("%s",&JOB.name);
		printf("\n%s需要分配的主存大小(单位:KB):",JOB.name);
		scanf("%d",&JOB.size); 
		node*p = wfp->next,*best = NULL;
		while(p != NULL)
		{
			if(p->size >= JOB.size && best == NULL)
			{
				best = p;
			}
			if(p->size >= JOB.size && p->size >best->size)
			{
				best = p;
			}
			p = p->next; 
		}
		node*NODE = (node*)malloc(sizeof(node));//创建节点插入已分配表中 
		NODE->next = NULL;
		NODE->size = JOB.size;
		NODE->address = best->address;
		int i=0;
		for(i=0;i<strlen(JOB.name);i++)
		{
			NODE->flag[i] = JOB.name[i];
		} 
		NODE->flag[i+1]='\0';
		 
		
		node*h = yfp;//修改已分配表 
		while(h->next != NULL)
		{
			h = h->next; 
		}
		h->next = NODE;
		
		node*hh = wfp->next;
		node*pre = wfp;
		while(hh != best)//修改未分配表 
		{
			pre=hh;
			hh = hh->next;
		}
		if(best->size == JOB.size)
		{
			pre->next = best->next;
		}
		else
		{
			best->address = best->address + JOB.size;
			best->size = best->size -JOB.size;
		}
		printf("\n分配成功!");
		print(yfp,wfp);
	}
} 
void release(node *yfp, node *wfp)
{
		print(yfp,wfp);
		printf("\n请输入要回收的作业名:"); 
		char NAME[20];
		scanf("%s",&NAME);
		
		node *h,*hpre;
		hpre = yfp;
		h = yfp->next;
		while(h!=NULL)
		{
			string str1,str2;
			str1 = h->flag;
			str2 = NAME;
			const char* p = str1.data();
			const char* p2 = str2.data();
			if(strcmp(p,p2)==0)
			{ 
				break; 
			} 
			hpre = h;
			h = h->next;
		}
		
		node *seek,*pre;
		seek = wfp->next;
		pre = wfp;
		while(seek!=NULL)
		{
			if(pre == wfp)
			{
				//printf("//更新未分配表的头部\n");
				if(h->address+h->size<=seek->address) 
				{
					if(h->address+h->size<seek->address)
					{
						hpre->next = h->next;
						h->next = seek;
						pre->next = h;
						h->flag[0] = '\0';
						break;
					}
					else
					{
						hpre->next = h->next;
						seek->address = h->address;
						seek->size = seek->size+h->size; 
						break;
					}
				}
			}
			else if(seek->next == NULL)
			{
				//printf("//更新未分配表的尾部\n");
				if(h->address >= seek->address +seek->size)
				{
					if(h->address > seek->address +seek->size)
					{
						hpre->next = h->next;
						h->next = NULL;
						seek->next = h;
						h->flag[0] = '\0';
						break;
					}
					else
					{
						hpre->next = h->next;
						seek->size = seek->size+h->size; 
						break;
					}
				}
				else
				{
					//printf("//更新未分配表的中部\n");
					if(pre->address+pre->size == h->address&&pre->address+pre->size+h->size<seek->address)
					{
						//printf("//有上邻空闲\n");
						pre->size  = pre->size+h->size;
						hpre->next = h->next;
						break;
					} 
					else if(pre->address+pre->size < h->address&&h->address + h->size == seek->address)
					{
						//printf("//有下邻空闲\n");
						seek->address = h->address;
						seek->size = seek->size+h->size;
						hpre->next = h->next;
						break;
					} 
					else if(pre->address+pre->size == h->address&&h->address + h->size == seek->address)
					{
						//printf("//有上、下邻空闲\n");
						pre->size = pre->size  + h->size +seek->size;
						pre->next = seek->next;
						hpre->next = h->next;
						break;
					} 
					else if(pre->address+pre->size < h->address&&h->address + h->size < seek->address)
					{
						//printf("//没有空闲\n");
						hpre->next = h->next;
						h->next = seek;
						pre->next = h;
						h->flag[0]='\0';
						break;
					} 
				}
			}
			else
			{
				//printf("//更新未分配表的中部\n");
				if(pre->address+pre->size == h->address&&pre->address+pre->size+h->size<seek->address)
				{
					//printf("//有上邻空闲\n");
					pre->size  = pre->size+h->size;
					hpre->next = h->next;
					break;
				} 
				else if(pre->address+pre->size < h->address&&h->address + h->size == seek->address)
				{
					//printf("//有下邻空闲\n");
					seek->address = h->address;
					seek->size = seek->size+h->size;
					hpre->next = h->next;
					break;
				} 
				else if(pre->address+pre->size == h->address&&h->address + h->size == seek->address)
				{
					//printf("//有上、下邻空闲\n");
					pre->size = pre->size  + h->size +seek->size;
					pre->next = seek->next;
					hpre->next = h->next;
					break;
				} 
				else if(pre->address+pre->size < h->address&&h->address + h->size < seek->address)
				{
					//printf("//没有空闲\n");
					hpre->next = h->next;
					h->next = seek;
					pre->next = h;
					h->flag[0]='\0';
					break;
				} 
			}
			pre = seek;
			seek = seek->next;
		}
		
		printf("\n回收成功!");
		print(yfp,wfp);
}
int main()
{
	int option=1;
	printf("请输入内存大小为:");
	scanf("%d",&memory.size);
	printf("\n请输入起始地址大小为:");
	scanf("%d",&memory.address);
	
	node*yfp = (node *)malloc(sizeof(node));
	yfp->next =NULL;
	node*wfp = (node *)malloc(sizeof(node));
	
	node*p = (node *)malloc(sizeof(node));
	p->size = memory.size;
	p->address = memory.address;
	p->flag[0]='\0';
	p->next = NULL;
	wfp->next = p;
	
	while(option)
	{
	printf("\n*****************可变分区管理*****************"); 
	printf("\n        *       1.内存管理       *");
	printf("\n        *       2.内存去配       *");
	printf("\n        *       0.退出           *");
	printf("\n                请输入选项:"); 
	scanf("%d",&option);
	if(option == 1)
	{
		govern(yfp,wfp);
	}
	else if(option == 2)
	{
		release(yfp,wfp);
	}
	}
}
//new malloc  没有真正接触内存 

运行结果

样例一:

fa3dc1bc4f224aad8ecb76a97509a44b.png

样例二:

9e8cf5116dc44b2ca91a4a1aa3fa4517.png

实验总结

①写程序之前的逻辑思路非常重要

②当遇到难理解的地方时一定要多想

③调用函数创建的单链表要注意是否要return,如果是带头节点的可以不用返回值,如果不是带头节点的要返回单链表

④最大的体会是在调用函数中创建的节点和调用函数中定义的变量二者的生存期不同

 

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模拟实现动态可变分区存储管理系统,内存资源的分配情况用一个单链表来表示,每一个节点表示一个可变分区,记录有内存首地址、大小、使用情况等,模拟内存分配动态输入构造空闲区表,键盘接收内存申请尺寸大小,根据申请,实施内存分配,并返回分配所得内存首址。分配完后,调整空闲区表,并显示调整后的空闲区表和已占用的区表。如果分配失败,返回分配失败信息。模拟内存回收。根据空闲区表,从键盘接收回收区域的内存作业代号。回收区域,调整空闲区表,并显示调整后的空闲区表。对于内存区间的分配,移出,合并就是相应的对链表节点信息进行修改,删除和创建相应的节点。 在模拟实现动态可变分区存储管理系统中用到的是“最佳适应算法”与“最坏适应算法”。所谓“最佳”是指每次为作业分配内存时,总是把满足要求、又是最小的空闲分区分配给作业,避免“大材小用”。因此保证每次找到的总是空闲分区中最小适应的,但这样会在储存器中留下许多难以利用的小的空闲区。最坏适应分配算法是要扫描整个空闲分区表或链表,总是挑选最大的一个空闲分区割给作业使用。进入系统时我们需要内存首地址和大小这些初始化数据。成功后我们可以自由的使用首次适应算法与最佳适应算法对内存进行分配。内存经过一系列分配与回收后,系统的内存分配情况不再连。首次适应算法与最佳适应算法的差异也就很容易的体现在分配时。动态可变分区存储管理模拟系统采用最佳适应算法、最坏适应算法内存调度策略,对于采用不同调度算法,作业被分配到不同的内存区间。
可变分区分配是一种存储管理技术,用于为进程分配内存空间。它的主要特点是分区大小不固定,可以根据进程的需要进行动态调整。在这种技术中,物理内存被划分为多个可变大小的分区,每个分区可以分配给一个进程使用。 下面是实验四的步骤: 1. 设计数据结构:设计数据结构来存储可用分区和已分配分区的信息,包括分区的起始地址、大小和状态等。 2. 初始化分区:将整个物理内存划分为一个或多个可用分区,并将其添加到可用分区列表中。 3. 进程申请内存:当进程需要内存时,它向操作系统发出请求。操作系统会在可用分区列表中查找一个大小足够的分区来满足进程的需要。 4. 分配分区:如果找到了一个合适的分区操作系统会将该分区标记为已分配,并从可用分区列表中删除该分区,然后将该分区的起始地址返回给进程。 5. 释放分区:当进程不再需要某个分区时,它将释放该分区操作系统将该分区标记为可用,并将其添加到可用分区列表中。 6. 内存回收:当所有进程都结束时,操作系统将所有已分配的分区标记为可用,以便下一批进程使用。 7. 碎片整理:在分配和释放分区的过程中,可能会出现内存碎片。为了最大化可用内存空间,可以实现碎片整理算法,将多个相邻的可用分区合并成一个更大的分区。 这些步骤可以通过编程实现。在实现过程中,需要注意保证数据结构的完整性和正确性,以及在内存分配和释放过程中避免死锁等问题的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值