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;
}
注:水平较菜,可能存在代码不简洁的部分,但是代码实测是可以跑的,仅供思路参考~