湖南师范大学 信息科学与工程学院 操作系统课程实验报告
实验项目名称: 可变分区存储管理
题目
实验一、可变分区存储管理
一、实验目的:
- 加深对可变分区存储管理的理解;
- 提高用C语言编制大型系统程序的能力,特别是掌握C语言编程的难点:指针和指针作为函数参数;
- 掌握用指针实现链表和在链表上的基本操作。
二、实验内容:
参照教材P137-P140的内容,编写一个C程序,用char *malloc(unsigned size)函数向系统申请一次内存空间(如size=1000,单位为字节),用循环首次适应算法、最佳适应算法和最坏适应算法,模拟可变分区存储管理,实现对内存区的分配和回收管理。
三、实验要求: - 分配函数addr=(char *)lmalloc(unsigned size)和释放函数lfree(unsigned size,char *addr)的参数size和addr,要以键盘命令的形式输入,每次分配和释放后显示空闲分区表。
- 空闲分区表可采用结构数组的形式(最低要求)或双向链表的形式。
四、参考测试数据:
操作系统在低地址占用100KB的空间,用户区主存从100KB处开始占用512KB。初始时,用户区全部为空闲,分配时截取空闲分区的低地址部分作为已分配区。执行以下申请、释放操作序列后:请求300KB,请求100KB,释放300KB,请求150KB,请求90KB,释放100KB。
代码实现
#include "stdio.h"
#include "iostream"
using namespace std;
void firstmethod();
void bestmethod();
void badmethod();
int main()
{
int menu;
do
{
cout << "------------------------------------------" << endl;
cout << "\n菜单:\n1.循环首次适应算法\n2.最佳适应算法\n3.最坏适应算法\n-------\n输入0结束程序\n请输入你要执行的操作:\n";
cout << "------------------------------------------" << endl;
cin >> menu;
switch (menu)
{
case 1:
cout << "*******************循环首次适应算法**********************" << endl;
firstmethod();
cout << "********************************************************" << endl;
break;
case 2:
cout << "*********************最佳适应算法************************" << endl;
bestmethod();
cout << "********************************************************" << endl;
break;
case 3:
cout << "*********************最坏适应算法************************" << endl;
badmethod();
cout << "********************************************************" << endl;
break;
case 0:
break;
default:
cout << "输入错误,请重新选择操作" << endl;
break;
}
} while (menu != 0);
}
typedef struct Double_linked_list
{
//char name[10];//进程名
int flag; //1为已分配,0为空闲
unsigned int size; //所指分区的大小
char *addr; //分区起始地址
struct Double_linked_list *prior, *next; //本表项的前后表项
} DllNode, *Dll;
Dll first, current; //首表项与起始查询指针
unsigned start; //主存起始地址
char *p; //地址的开始
//初始化空闲分区表
void initDll()
{
first = (Dll)malloc(sizeof(DllNode));
if (!first)
{
//分配失败
exit(0);
}
printf("请输入你要设置的主存起始地址:\n");
cin >> start;
printf("请输入你要设置的主存大小:\n");
cin >> first->size;
p = (char *)malloc(first->size + start);
first->addr = p + start;
first->flag = 0;
first->next = first->prior = NULL;
}
void printDll()
{
Dll tmp = first;
cout << "\n\n-----------------free table---------------" << endl;
while (tmp != NULL)
{
if (!tmp->flag)
printf("起始地址:%4u,大小:%4d,结束地址:%4u\n", tmp->addr - p, tmp->size, tmp->addr - p + tmp->size - 1);
tmp = tmp->next;
}
cout << "------------------------------------------" << endl;
tmp = first;
cout << "----------------allowcation table---------" << endl;
while (tmp != NULL)
{
if (tmp->flag)
printf("起始地址:%4u,大小:%4d,结束地址:%4u\n", tmp->addr - p, tmp->size, tmp->addr - p + tmp->size - 1);
tmp = tmp->next;
}
cout << "------------------------------------------\n\n"
<< endl;
}
int lmalloc(unsigned size)
{
if (size <= 0)
{
cout << "分配大小错误" << endl;
return 1;
}
Dll tmp = current;
Dll newNode = (Dll)malloc(sizeof(DllNode));
if (!newNode)
exit(0);
newNode->flag = 1;
newNode->size = size;
do
{
if (current->flag == 1)
{ //已分配的区域跳过
current = current->next;
if (!current)
{
current = first;
}
continue;
}
if (current->size > size)
{ //大于所需空间
if (current == first)
{
first = newNode;
if (current->next == current)
{
current->next = first;
}
current->prior = newNode;
}
else
{
current->prior->next = newNode;
}
newNode->prior = current->prior;
newNode->next = current;
current->prior = newNode;
newNode->addr = current->addr;
current->addr += size;
current->size -= size;
return 1;
}
else if (current->size == size)
{ //等于所需空间
current->flag = 1;
current = current->next;
if (current == NULL)
{
current = first;
}
return 1;
}
else
{ //小于所需空间
current = current->next;
}
if (current == NULL)
{
current = first;
}
} while (tmp != current);
return 0;
}
int lfree(unsigned size, unsigned addr)
{
Dll tmp = first;
do
{
//为空闲分区则跳过
if (tmp->flag == 0)
{
tmp = tmp->next;
continue;
}
//起始地址或大小不符
if (tmp->addr - p != addr || tmp->size != size)
{
tmp = tmp->next;
continue;
}
//回收链表第一个节点
if (tmp->prior == NULL)
{
//链表只有一个节点
if (tmp->next == NULL)
{
tmp->flag = 0;
return 1;
}
//链表的第一个节点且后面有节点
else
{
//回收链表的第一个节点且后面一个节点为空闲分区
if (!tmp->next->flag)
{
tmp->size += tmp->next->size;
Dll p = tmp->next;
tmp->next = tmp->next->next;
tmp->flag = 0;
free(p);
return 1;
}
//回收链表的第一个节点且后面一个节点不是空闲分区
else
{
tmp->flag = 0;
return 1;
}
}
}
if (tmp->next == NULL)
{ //回收链表最后一个节点
if (!tmp->prior->flag)
{ //前面的节点是空闲分区
tmp->prior->size += tmp->size;
tmp->prior->next = tmp->next;
free(tmp);
return 1;
}
else
{ //前面分区已分配
tmp->flag = 0;
return 1;
}
}
//此时的节点不是首尾分区
//回收分区前有空闲分区
if (!tmp->prior->flag)
{
//回收分区前后都有空闲分区
if (!tmp->next->flag)
{
tmp->prior->size += tmp->size + tmp->next->size;
tmp->prior->next = tmp->next->next;
free(tmp->next);
free(tmp);
return 1;
}
//回收分区后没有空闲分区
else
{
tmp->prior->size += tmp->size;
tmp->prior->next = tmp->next;
free(tmp);
return 1;
}
}
//回收分区前没有空闲分区
else
{
//回收分区后有空闲分区
if (!tmp->next->flag)
{
tmp->size += tmp->next->size;
Dll p = tmp->next;
tmp->next = tmp->next->next;
tmp->flag = 0;
free(p);
return 1;
}
//回收分区前后都没有
else
{
tmp->flag = 0;
return 1;
}
}
} while (tmp != NULL);
//没有要释放的分区
return 0;
}
void firstmethod()
{
int menu;
initDll();
current = first;
unsigned size, addr;
do
{
printDll();
cout << "------------------------------------------\n菜单:\n1.申请内存\n2.释放内存\n------------------------------------------\n输入0结束本次算法\n";
cin >> menu;
switch (menu)
{
case 1:
cout << "请输入申请内存大小:" << endl;
cin >> size;
if (!(lmalloc(size)))
{
cout << "内存不足,分配失败" << endl;
}
break;
case 2:
cout << "请输入要释放的起始地址" << endl;
cin >> addr;
cout << "请输入要释放的地址大小:" << endl;
cin >> size;
if (!lfree(size, addr))
{
cout << "命令错误,请检查分配表" << endl;
}
break;
case 0:
free(first);
break;
default:
cout << "输入错误,请重新选择操作" << endl;
break;
}
} while (menu != 0);
}
void swap_Dll(Dll &L1, Dll &L2)
{
char *p = L1->addr;
L1->addr = L2->addr;
L2->addr = p;
int flag = L1->flag;
L1->flag = L2->flag;
L2->flag = flag;
int size = L1->size;
L1->size = L2->size;
L2->size = size;
}
void sortDll_ASC_size(Dll &L)
{
Dll p, q;
for (p = L; p->next != NULL; p = p->next)
{
for (q = p->next; q != NULL; q = q->next)
{
if (p->size > q->size)
{
swap_Dll(p, q);
}
}
}
}
void sortDll_DSC_size(Dll &L)
{
Dll p, q;
for (p = L; p->next != NULL; p = p->next)
{
for (q = p->next; q != NULL; q = q->next)
{
if (p->size < q->size)
{
swap_Dll(p, q);
}
}
}
}
void sortDll_ASC_addr(Dll &L)
{
Dll p, q;
for (p = L; p->next != NULL; p = p->next)
{
for (q = p->next; q != NULL; q = q->next)
{
if (p->addr > q->addr)
{
swap_Dll(p, q);
}
}
}
}
int lmalloc_other(unsigned size)
{
if (size <= 0)
{
cout << "分配大小错误" << endl;
return 1;
}
Dll tmp = first;
Dll newNode = (Dll)malloc(sizeof(DllNode));
if (!newNode)
exit(0);
newNode->flag = 1;
newNode->size = size;
do
{
if (tmp->flag == 1)
{ //已分配的区域跳过
tmp = tmp->next;
continue;
}
if (tmp->size > size)
{ //大于所需空间
//第一个节点
if (tmp == first)
{
first = newNode;
newNode->prior = NULL;
}
else
{
tmp->prior->next = newNode;
newNode->prior = tmp->prior;
}
newNode->next = tmp;
tmp->prior = newNode;
newNode->addr = tmp->addr;
tmp->addr += size;
tmp->size -= size;
return 1;
}
else if (tmp->size == size)
{ //等于所需空间
tmp->flag = 1;
tmp = tmp->next;
return 1;
}
else
{ //小于所需空间
tmp = tmp->next;
}
} while (tmp != NULL);
return 0;
}
void bestmethod()
{
int menu;
initDll();
unsigned size, addr;
do
{
printDll();
cout << "------------------------------------------\n菜单:\n1.申请内存\n2.释放内存\n------------------------------------------\n输入0结束本次算法\n";
cin >> menu;
switch (menu)
{
case 1:
sortDll_ASC_size(first);
cout << "请输入申请内存大小:" << endl;
cin >> size;
if (!(lmalloc_other(size)))
{
cout << "内存不足,分配失败" << endl;
}
sortDll_ASC_addr(first);
break;
case 2:
sortDll_ASC_addr(first);
cout << "请输入要释放的起始地址" << endl;
cin >> addr;
cout << "请输入要释放的地址大小:" << endl;
cin >> size;
if (!lfree(size, addr))
{
cout << "命令错误,请检查分配表" << endl;
}
break;
case 0:
free(first);
break;
default:
cout << "输入错误,请重新选择操作" << endl;
break;
}
} while (menu != 0);
}
void badmethod()
{
int menu;
initDll();
unsigned size, addr;
do
{
printDll();
cout << "------------------------------------------\n菜单:\n1.申请内存\n2.释放内存\n------------------------------------------\n输入0结束本次算法\n";
cin >> menu;
switch (menu)
{
case 1:
sortDll_DSC_size(first);
cout << "请输入申请内存大小:" << endl;
cin >> size;
if (!(lmalloc_other(size)))
{
cout << "内存不足,分配失败" << endl;
}
sortDll_ASC_addr(first);
break;
case 2:
sortDll_ASC_addr(first);
cout << "请输入要释放的起始地址" << endl;
cin >> addr;
cout << "请输入要释放的地址大小:" << endl;
cin >> size;
if (!lfree(size, addr))
{
cout << "命令错误,请检查分配表" << endl;
}
break;
case 0:
free(first);
break;
default:
cout << "输入错误,请重新选择操作" << endl;
break;
}
} while (menu != 0);
}
实验结果分析
操作系统在低地址占用100KB的空间,用户区主存从100KB处开始占用512KB。初始时,用户区全部为空闲,分配时截取空闲分区的低地址部分作为已分配区。执行以下申请、释放操作序列后:请求300KB,请求100KB,释放300KB,请求150KB,请求90KB,释放100KB。
首次循环适应算法
最佳适应算法
最坏适应算法
心得体会
这次实验是实现动态分区分配中循环首次适应算法,最佳适应算法和最坏适应算法,三种算法大同小异,在循环首次适应算法中,需要注意的是用current指针指向上一次分配后的空闲分区,在分配时从current指向的分区开始查询。而最佳适应算法和最坏适应算法只需将空闲分区在分配前分别按升序和降序进行排列,在分配后对地址进行升序排列,剩下的分配和回收细节基本相同。