一、算法基本思想
可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表。当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。为了方便查找还可使表格“紧缩”,总是让“空表目”栏集中在表格的后部。采用最先适应算法(顺序分配算法)分配主存空间。按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。当空闲区大于需要量时,一部分用来装入作业,另一部分仍为空闲区登记在空闲区说明表中。由于本实验是模拟主存的分配,所以把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。
分配的流程图:
当一个作业执行结束撤离时,作业所占的区域应该 归还,归还的区域如果与其它空闲区相邻,则应合成一个较 大的空闲区,登记在空闲区说明表中。例如,在提示(1) 中列举的情况下,如果作业2撤离,归还所占主存区域时, 应与上、下相邻的空闲区一起合成一个大的空闲区登记在空闲区说明表中。归还时的流程图如下:
二、程序所用的数据结构和符号说明
函数FIRST_FIT()提供功能选择页面,函数init()初始化空闲区信息,在该步中已经装入三个作业,函数input()装入作业分配内存,函数finish()撤销作业回收内存,函数merge()实现相邻空闲区合并操作,函数sort()让空闲区按照起始地址从小到大排序,output1和output2实现相关输出展示。
三、具体实现
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <iomanip>
#define n 100 // 最大空闲区个数
using namespace std;
int p_num = 4; // 作业个数
int num = 2; // 空闲区个数
struct
{
char name[20];
int address;
int length;
int flag;
} free_table[n], work_table[n], temp;
void sort() // 空闲区按起始地址从小到大排序
{
int i;
for (i = 0; i < num - 1; i++)
for (int j = 0; j < num - i - 1; j++)
if (free_table[j].address > free_table[j + 1].address)
{
temp = free_table[j];
free_table[j] = free_table[j + 1];
free_table[j + 1] = temp;
}
for (i = 0; i < p_num - 1; i++)
for (int j = 0; j < p_num - i - 1; j++)
if (work_table[j].address > work_table[j + 1].address)
{
temp = work_table[j];
work_table[j] = work_table[j + 1];
work_table[j + 1] = temp;
}
}
void merge() // 扫描空闲区若前后有相邻空闲区则合并
{
for (int i = 0; i < num-1; i++)
{
if (free_table[i].address + free_table[i].length == free_table[i+1].address)
{
if(!free_table[i].flag && !free_table[i+1].flag)
{
free_table[i].length += free_table[i+1].length;
for (int j = i+1; j < num-1; j++)
free_table[j] = free_table[j + 1];
i--;
num--;
}
}
}
}
void output1() // 输出空闲区表信息
{
cout << "空闲区表:" << endl << " 起始地址" << "\t" << "长度" << "\t"<<"状态" <<endl;
for (int i = 0; i < num; i++)
cout << "\t" << free_table[i].address << "\t" << free_table[i].length << "\t" <<free_table[i].flag << endl;
cout << endl ;
}
void output2() // 输出已分配区表信息
{
cout << "已分配区表:" << endl << " 起始地址" <<"\t" << "长度" <<"\t" <<"状态" << "\t" <<"占用作业" <<endl;
for (int i = 0; i < p_num; i++)
cout << "\t" <<work_table[i].address << "\t" << work_table[i].length << "\t" << work_table[i].flag <<"\t" <<work_table[i].name << endl;
cout << endl;
}
// 初始化空闲区信息
void init()
{
cout <<"------------最先适应算法------------" << endl ;
work_table[0].address =0;
work_table[0].length =10;
work_table[0].flag = 1 ;
strcpy(work_table[0].name, "操作系统");
work_table[1].address = 10;
work_table[1].length= 4;
work_table[1].flag = 1;
strcpy(work_table[1].name, "1");
work_table[2].address = 32;
work_table[2].length= 96;
work_table[2].flag = 1;
strcpy(work_table[2].name, "2");
work_table[3].address = 14;
work_table[3].length= 12;
work_table[3].flag = 1;
strcpy(work_table[3].name, "3");
free_table[0].address = 26;
free_table[0].length =6;
free_table[0].flag = 0;
free_table[1].address = 128;
free_table[1].length =896;
free_table[1].flag = 0;
sort();
merge();
cout << endl ;
sort();
output1();
output2();
}
// 装入作业,分配内存
void input()
{
int i, length;
char name[20];
cout << "输入作业序号: ";
gets(name);
cout << "输入作业大小: ";
cin >> length;
fflush(stdin);
for (i = 0; i < num; i++)
{
if(!free_table[i].flag)
{
if (length < free_table[i].length)
{
work_table[p_num].address = free_table[i].address;
free_table[i].length = free_table[i].length - length;
free_table[i].address = free_table[i].address + length;
strcpy(work_table[p_num].name, name);
work_table[p_num].flag = 1;
work_table[p_num].length = length;
p_num++;
break;
}
else if (length == free_table[i].length)
{
strcpy(work_table[p_num].name, name);
work_table[p_num].flag = 1;
work_table[p_num].address = free_table[i].address;
work_table[p_num].length = free_table[i].length;
p_num++;
for(int j=i; j<num; j++)
{
free_table[j]=free_table[j+1];
}
num--;
break;
}
}
}
if (i == num)
{
cout << endl << "无合适空闲区,不能为作业分配内存!" << endl;
return;
}
sort();
output1();
output2();
}
// 撤消作业,回收内存
void finish()
{
char name[20];
int i;
cout <<"输入作业序号:";
gets(name);
fflush(stdin);
bool flag = 0;
for (i = 0; i < p_num; i++)
{
if (!strcmp(name, work_table[i].name))
{
free_table[num] = work_table[i];
free_table[num].flag = 0;
num++;
sort();
merge();
for(int j = i; j < p_num; j++)
work_table[j] = work_table[j+1];
p_num--;
flag = 1;
break;
}
}
if (!flag)
cout << endl <<"没有此作业,重新输入!";
output1();
output2();
}
void FIRST_FIT()
{
init();
while (1)
{
int c;
cout << "1.装入作业" << endl << "2.撤销作业" << endl << "3.退出" <<"请输入你的选择:";
cin >> c;
cout <<endl;
fflush(stdin);
if (c == 1)
input();
else if (c == 2)
finish();
else break;
}
}
int main(void)
{
FIRST_FIT();
return 0;
}
四、实验结果
假设主存中已装入三个作业,且形成两个空闲区,确定空闲区说明表的初值。现有一个需要主存量为6K的作业4申请装入主存;然后作业3撤离;再作业2撤离。请你为它们进行主存分配和回收,把空闲区说明表的初值以及每次分配或回收后的变化显示出来或打印出来。