操作系统实验 分区管理

Pt1.原理

———————————————————————————

可变分区调度算法

1.最先适应分配算法
2.最优适应分配算法
3.最坏适应算法
注:本文代码部分采用最先适应分配方法

最先适应算法(first fit algorithm)

可用表或自由链按起始地址递增的次序排列,一旦找到大于或等于所要求内存长度的分区,则结束搜索。

最佳适应算法(best fit algorithm)

从小到大的次序组成空闲区可用表或自由链,从表头开始查找,当找到第一个满足要求的空闲区是,停止查找。

最坏适应算法(worst fit algorithm)

空闲区按其大小递减的顺序组成空闲区可用表或自由链。当用户作业或进程申请一个空闲区是,先检查空闲区可用表或自由链的第一个空闲可用区的大小是否大于或等于所要求的的内存长度,若可用表或自由链的第一个项长度小于所要求的的,则分配失败,否则从空闲区可用表或自由链中分配相应的存储空间给用户,然后修改空闲区可用表或自由链。

思路步骤

  1. 用户提出内存空间的申请
  2. 根据申请者的要求,系统按照一定的分配策略分析内存空间的使用情况,找出能满足请求的空闲区,分给申请者
  3. 当程序执行完毕或主动归还内存资源时,系统要收回它所占用的内存空间或它归还的部分内存空间。
  • 根据可变分区的主存分配思想:
    (1)首先设计记录主存使用情况的数据表格,用来记录空闲区和作业占用的区域,即“已分配区表”和“空闲区表”
    (2)然后在数据表上进行主存的分配
    (3)其主存分配算法选择一种算法
    (4)程序中可选择进行主存分配或主存回收
    (5)若是主存分配,输入作业名和所需主存空间大小
    (6)若是回收,输入回收作业名
    (7)以循环进行主存分配和回收

内存分配

当要装入一个作业时,从空闲区表中查找标志为“未分配”的空闲区,从中找一个能容纳该作业的空闲区。
1.如果找到的空闲区正好等于该作业的长度,则把该分区全部分配给该作业。这时应该把该空闲区登记栏中的标志改为“空”,同时在已分配区表中找到一个标志为“空”的栏目登记新装入作业所占用分区的起始地址、长度和作业名。
2.如果找到的空闲区大于作业长度,则把空闲区分成两部分,一部分用来装入作业,另一部分仍然为空闲区,这时只要修改空闲区的长度,且把新装入的作业登记到已分配区表中。(本实验中采用首次适应算法、循环首次适应算法、最坏适应算法中的一种为作业分配主存)。

内存回收

在实现回收时,
1.首先将作业归还的区域 在 已分配表中找到,将该栏目的状态变为“空”,
2.然后检查空闲区表中标志为“未分配”栏目,
3.查找是否又相邻空闲区;最后合并空闲区,修改空闲区表。
注意:动态分区方式下回收主存空间时应该检查是否有与归还区相邻的空闲区域。若有,则应该合并成一个空闲区:
一个归还区可能有上邻空闲区,也可能有下邻空闲区,或者既有上邻空闲区又有下邻空闲区,或者既无上邻空闲区也无下邻空闲区。

分区管理的主要优缺点

1. 优点

  • 实现了多个作业或进程对内存的共享,有助于多道程序设计,从而提高了系统的资源利用率。
  • 该方法要求的硬件支持少,管理算法简单,因而实现容易。

2. 缺点

  • 内存利用率不高。和单一连续分配算法一样,内存可能含有从未用过的信息。而且,还存在着严重的碎小空闲区(碎片)不能利用的问题,这更进一步影响了内存的利用率。
  • 作业或进程的大小受分区大小控制,除非配合采用覆盖和交换技术。
  • 无法实现各分区间的信息共享。

Pt2. 源码实现

———————————————————————————

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#define MAX_SIZE 20
#include<string.h>
using namespace std;

//已分配区表的定义 
#define U 10 //假定系统允许的最大作业数量为U 
struct Used
{
int address; //已分分区起始地址,default (-1)
int length; //已分分区长度,单位为字节 default (-1)
int flag;//已分配表区登记栏标志,用0表示空栏目,
};//已分配区表

//空闲区表的定义:
#define F 10//假定系统允许的空闲区表最大为m
struct Free
{
int address;//空闲区起始地址,default (-1)
int length;//空闲区长度,单位为字节 default (-1)
int flag;//空闲区表登记栏目用0表示空栏目,1表示未分配
};//空闲区表

#define M 100//假定内存共1000个存储空间 
struct Memory
{
	string name;//存储作业名,default( |) 
	int flag;// 已使用则flag为1,default(0) 
}; 


//选项函数 
int option(){
	int option;
	printf("请选择:\n");
	printf("主存分配----- 1\n");
	printf("主存回收----- 2\n");
	printf("退出----------3\n");
	printf("请输入您的选择:");
	scanf("%d",&option);
	if(option == 1) return 1;
	if(option == 2) return 2;
	if(option == 3) exit(0); 
} 


void line(){
	printf("--------------------------------------------------\n");
}

//初始化 
void init(struct Used used_table[],struct Free free_table[],struct Memory memory[]){
	int i;
	for(i=0;i<U;i++){
		used_table[i].address = -1;
		used_table[i].length = -1;
		used_table[i].flag = 0;
	}
	
	free_table[0].address = 0;
	free_table[0].length = M;
	free_table[0].flag = 1;
	for(i=1;i<F;i++){
		free_table[i].address = -1;
		free_table[i].length = -1;
		free_table[i].flag = 0;
	}
	
	for(i=0;i<M;i++){
		memory[i].name = "  |";
		memory[i].flag = 0;
	}
}

//内存分配 (最先适应算法) 
void distribute(struct Used used_table[],struct Free free_table[],struct Memory memory[]){
	printf("请输入要存入的作业名:");
	string str;
	cin>> str;
	printf("该作业所需主存空间大小:"); 
	int size;
	scanf("%d",&size);
	
	int i;
	for(i=0;i<F;i++){
		//在空闲区找到一个标志为“未分配 "且空闲区长度大于等于作业所需长度的区域 
		if(free_table[i].flag==1 && free_table[i].length>=size)
		break;//找到该区域,跳出循环做下一操作 
		
		else{
			printf("主存空间不足!!!"); 
			break;
			exit(0);
			//return option();
		}
	}
	
	//存入内存 
	int t;
	for(t=0;t<M+1;t++){
		if(memory[t].flag == 0) break;  //在主存中找到首个空地址 t 
	}
	memory[t].name = str;  //在存储作业的区块首地址存出作业名 
	for(int j=t;j<t+size;j++){ //已存单元falg变为1;
	 //printf("%d\t%d\n",j,t);
		memory[j].flag = 1;
    }

	// 登记到已分配表
	int k;
	for(k=0;k<U+1;k++){
		if(used_table[k].flag==0){//找到一个未使用的分配栏 
		//printf("找到未使用的分配栏!\n"); 
			break;//找到 k 
		}
	}
	if(k==U+1){
		printf("分配区满!!!"); 
		exit(0);
	}
			
	used_table[k].address = free_table[i].address;//登记该作业首地址 
	used_table[k].length = size;//登记该作业长度 
	used_table[k].flag = 1; //更改该栏目标志 
	
	//向后更新空闲区表
	free_table[i].address += size; //该栏首地址向后移动作业大小个存储空间 
	free_table[i].length -= size;  //该栏长度减小作业大小个存储空间 
	free_table[i].flag = 1; //falg不变仍为1; 
	
}

//内存回收 
void recaim(struct Used used_table[],struct Free free_table[],struct Memory memory[]){
	//printf("IN!!\n");
	string str;
	printf("请输入要回收的作业名:");
	cin>>str;
	int i;
	for(i=0;i<M+1;i++){
		if(memory[i].name == str)  break; //找到该作业在主存中的位置,i即为该作业的首地址 
	}
	
	if(i == M+1){
		printf("没有该项作业!");
		exit(0); 
	}
	
	//将该作业在已分配表中找到
	int j;
	for(j=0;j<U;j++){
		if(used_table[j].address == i){ //如果在分配表的第j栏中有首地址与i值对上了 
		break; //记录该 j 
		}
	}
	used_table[j].flag = 0;//更改标志 
	
	//更新空闲区表 
	//情况1:检查空闲区是否有可以合并的栏目 
	int k;
	int judge2=0;//用于判断是否有与该作业相邻的空闲区 
	for(k=-1;k<F;k++){
		
		//(1)该作业只有前相邻的空闲区 
		if(free_table[k].address+free_table[k].length == used_table[j].address && !(free_table[k+1].address == used_table[j].address+used_table[j].length) )
		{ //将空闲区该栏长度更新 
		printf("stu1.1!!!!\n");
			free_table[k].length += used_table[j].length; //新的空闲长度 等于 原空闲长度 加上 作业长度 
			judge2=1; 
		}
		
		//(2)该作业只有后相邻的空闲区
		if( !(free_table[k].address+free_table[k].length == used_table[j].address) && (free_table[k+1].address == used_table[j].address+used_table[j].length) )
		{  //将空闲区该栏首地址和长度都更新 
		printf("stu1.2!!!!\n");
			free_table[k+1].address -= used_table[j].length; //新的空闲区首地址 等于 原空闲区首地址 减去 作业长度 
			free_table[k+1].length +=  used_table[j].length; //新的空闲长度 等于 原空闲长度 加上 作业长度 
			judge2=1;
		}
		
		//(3)该作业前后都有相邻的空闲区 
		if( (free_table[k].address+free_table[k].length == used_table[j].address) && (free_table[k+1].address == used_table[j].address+used_table[j].length) ) 
		{  //将空闲区较前的栏首地址保留,长度更新
		   //较后的栏初始化 
		   printf("stu1.3!!!!\n");
		   free_table[k].length += ( used_table[j].length + free_table[k+1].length ); //新的空闲长度 等于 原前空闲区长度 加上 作业长度  加上 后空闲区长度 
		   free_table[k+1].address = -1;
		   free_table[k+1].length = -1;
		   free_table[k+1].flag = 0;
		   judge2=1;
		}
	}
	
	if(judge2 == 0){//情况2:没有相邻的空闲区栏目,到空闲区表中根据首地址找作业相应的栏 更改信息 
	printf("stu2!!!!\n");
	
	int v; 
	for(v=0;v<F+1;v++){
		if(free_table[v].flag == 0){ //在空闲区新的栏目添加信息 
			
			free_table[v].flag = 1; //标志不变 
		    free_table[v].length = used_table[j].length;
		    free_table[v].address = used_table[j].address;
		    break;
		}
	}
		
	//printf("%d\t%d\t%d\t%d\n",v,free_table[v].flag,free_table[v].length,free_table[v].address);
	
	if(v == F+1){
		printf("空闲区表溢出!!!");
		exit(0);
	}		
	} //空闲区的两种情况分析结束,空闲区更新完毕
	
	printf("judge2:%d\n",judge2);
	//利用该回收作业在分配表中还未更变的长度和首地址信息,着手处理内存 
	memory[i].name = "  |";
	for(int r=i;r<used_table[j].length+i;r++){
		memory[r].flag = 0;
	}
	
	
    //最后处理已分配表(该回收作业标志已更改,还需初始化长度以及首地址) 
    used_table[j].length = -1;
    used_table[j].address = -1;
 	
}

//展示表 
void show_table(struct Used used_table[],struct Free free_table[]){   
	int i;
	printf("****[Used Table]****\n");
	printf("adr\tlen\tflag\n");
	for(i=0;i<U;i++){
		printf("%d\t%d\t%d\n",used_table[i].address,used_table[i].length,used_table[i].flag);
	}
	line();
	printf("****[Free Table]****\n");
	printf("adr\tlen\tflag\n");
	for(i=0;i<F;i++){
		printf("%d\t%d\t%d\n",free_table[i].address,free_table[i].length,free_table[i].flag);
	}
	line();
}

//展示内存 
void show_memory(struct Memory memory[]){
	line();
	printf("****[Memory Partition]****\n");
	printf("Pname\tflag\n");
	for(int i=0;i<M;i++){
		cout<<memory[i].name<<'\t'<<memory[i].flag<<endl;
	}
	line();
} 


int main(){
	
	struct Used used_table[U];
	struct Free free_table[F];
	struct Memory memory[M];
	init(used_table,free_table,memory);//函数实参中 用数组名 
	show_table(used_table,free_table);
	show_memory(memory);
	
	while(1){
	int judge=option();
	switch(judge){
		case 1: distribute(used_table,free_table,memory); break;
		case 2:recaim(used_table,free_table,memory); break;
		default: printf("error!!");exit(0);
	}
	show_table(used_table,free_table);
	int tmp;
	printf("是否查看内存?\n");
	printf("YES------1\n");
	printf("NO-------2\n");
	scanf("%d",&tmp);
	while(tmp == 1){
		show_memory(memory);
		break;
	}
	}
}

码字不易!
if ( 有幸有所帮助 ){
点赞收藏的都是帅哥靓女 o ^ - ^ o;
}

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狱典司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值