-
实验目的
1.对理论课中学习的内存管理当中的概念做进一步的理解;
2. 明白内存管理的主要任务;
3.了解内存管理任务的主要实现方法;
4.掌握内存的分配,回收等主要算法的原理;
5. 通过编程,熟悉分区式存储管理方法中内存分配回收算法的实现方式。
-
设计要求
该模拟实验中,为了实现动态多分区的分配和回收,主要要解决四个问题。
设计用来记录主存使用情况的数据结构,登记空闲区和已分配区占用的情况。
在设计好的该数据结构上面,模拟实现三种主存分配算法(First_Fit,Best_Fit,Worst_Fit)在设计好的该数据结构上面,模拟实现主存回收算法,要求回收时相邻空闲区合并。
设计好用户界面,显示可供用户选择的功能,并可根据用户要求显示当前内存使用情况。
-
设计思想及内容
编写程序,由必要的数据结构、主函数、主存分配函数和主存回收函数构成。实现在可变分区管理方式下,采用三种主存分配算法对主存分配与回收的模拟。
在主存分配函数中,要求实现的基本功能操作:寻找空闲分区,空闲分区表的修改,已分配分区表的修改。其中,若寻找到的最小适合空间相对作业请求的空间来说仍过大,则要分割该分区。
在主存回收函数中,要求实现的基本功能操作:回收作业释放的分区、修改已分配分区表、修改空闲分区表。其中,若回收的分区有上邻空闲分区或(和)下邻空闲分区的,要合并成为一个空闲分区,登记在空闲分区表的一个表项里。
-
实验原理
内存分配:用户输入作业名称和所需大小,系统根据选择的算法(首次适应、最佳适应、最差适应)在空闲分区表中找到合适的空闲分区,并将其标记为已分配。
内存回收:用户输入要回收的作业名称,系统找到对应的已分配分区,将其释放回空闲分区表,并尝试合并相邻的空闲分区以减少内存碎片
-
实验所用函数
init():初始化函数,设置初始空闲分区表,将整个内存空间标记为一个空闲分区,初始化空闲分区数量和已分配分区数量。
sort():对空闲分区表进行排序,以便快速找到合适的分区进行分配。这个函数在代码中没有被调用,可能是遗留代码。
find_insert():在已分配分区表中找到合适的插入位置,确保已分配分区表按地址排序。
first_fit():首次适应算法,从空闲分区表中找到第一个足够大的空闲分区进行分配。
best_fit():最佳适应算法,从空闲分区表中找到能够满足作业大小且自身大小最小的空闲分区进行分配。
worst_fit():最差适应算法,从空闲分区表中找到能够满足作业大小且自身最大的空闲分区进行分配。
find_best() 和 find_worst():辅助函数,分别用于 best_fit 和 worst_fit 算法,用于找到最佳和最差的空闲分区。
show():显示当前空闲分区表和已分配分区表的内容。
free():释放内存,将已分配的分区重新添加到空闲分区表中,并尝试与相邻空闲分区合并。
recover():回收作业,根据作业名称找到对应的已分配分区,并将其释放回空闲分区表。
-
实验代码
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<pthread.h>
#include<semaphore.h>
#include<string>
#include<iomanip>
using namespace std;
std::string expected_username="wx123";
std::string expected_password="123456";
const int max_size=100;
const int max_len=10000;
typedef struct partition_node
{
int name; //作业名称
int address; //分区起始地址
int length; //分区地址,单位为字节
int flag; //0 1 分区表的标志项
}p_node;
p_node free_table[max_size],used_table[max_size];
int free_number,used_number;
void init()
{
free_table[0].address=0;
free_table[0].length=max_len;
for(int i=1;i<max_size;i++)
{
free_table[i].address=-1;
free_table[i].length=0;
used_table[i].flag=0;
used_table[i].address=-1;
used_table[i].length=0;
used_table[i].flag=1;
}
free_number=1;
used_number=0;
}
void sort(){
int i,j,p;
for(i=0;i<free_number-1;i++){
p=i;
for(j=i+1;j<used_number;j++){
if(free_table[j].length<free_table[p].length){
p=j;
}
}
if(p!=i){
free_table[free_number]=free_table[i];
free_table[i]=free_table[p];
free_table[p]=free_table[free_number];
}
}
}
int find_insert(p_node *table,int number,int address)
{
if(number==1) return 0;
for(int i=0;i<number;i++)
{
if(i==0&&table[i].address>address)
{
for(int j=number-1;j>0;j--)
table[j]=table[j-1];
return 0;
}
else if(i==number-1&&table[i].address<address)
{
return i;
}
else if(table[i].address<address&&table[i+1].address>address)
{
for(int j=number-1;j>i+1;j--)
table[j]=table[j-1];
return i+1;
}
}
}
void first_fit()
{
int job_name;
int job_length;
int i,index;
cout<<"请输入作业的名称和大小"<<endl;
scanf("%d%d",&job_name,&job_length);
for(i=0;i<free_number;i++)
{
if(free_table[i].length>=job_length)
{
index=i;
break;
}
}
if(i>=free_number)
{
cout<<"内存分配失败!当前没有能满足你申请的长度的内存空间!"<<endl;
return ;
}
used_table[used_number].address=free_table[index].address;
used_table[used_number].name=job_name;
used_table[used_number].length=job_length;
if(free_table[index].length>job_length)
{
free_table[index].address+=job_length;
free_table[index].length-=job_length;
}
else
{
for(i=index;i<free_number-1;i++)
free_table[i]=free_table[i+1];
free_number--;
}
cout<<"内存分配成功!"<<endl;
used_number++;
}
int find_best(int job_length)
{
int min=max_len;
int ans=-1;
int i;
for(i=0;i<free_number;i++)
{
if(free_table[i].length>job_length&&free_table[i].length<=min)
{
min=free_table[i].length;
ans=i;
}
}
return ans;
}
void best_fit()
{
int job_name;
int job_length;
int i,index;
cout<<"请输入作业的名称和大小"<<endl;
scanf("%d%d",&job_name,&job_length);
if((index=find_best(job_length))==-1)
{
cout<<"内存分配失败!当前没有能满足你申请的长度的内存空间!"<<endl;
return ;
}
used_number++;
int k=find_insert(used_table,used_number,free_table[index].address);
used_table[k].address=free_table[index].address;
used_table[k].name=job_name;
used_table[k].length=job_length;
if(free_table[index].length>job_length)
{
free_table[index].address+=job_length;
free_table[index].length-=job_length;
}
else
{
for(i=index;i<free_number-1;i++)
free_table[i]=free_table[i+1];
free_number--;
}
cout<<"内存分配成功!"<<endl;
}
int find_worst(int job_length)
{
int max=0;
int ans=-1;
int i;
for(i=0;i<free_number;i++)
{
if(free_table[i].length>job_length&&free_table[i].length>max)
{
max=free_table[i].length;
ans=i;
}
}
return ans;
}
void worst_fit()
{
int job_name;
int job_length;
int i,index;
cout<<"请输入作业的名称和大小"<<endl;
scanf("%d%d",&job_name,&job_length);
if((index=find_worst(job_length))==-1)
{
cout<<"内存分配失败!当前没有能满足你申请的长度的内存空间!"<<endl;
return ;
}
used_number++;
int k=find_insert(used_table,used_number,free_table[index].address);
used_table[k].address=free_table[index].address;
used_table[k].name=job_name;
used_table[k].length=job_length;
if(free_table[index].length>job_length)
{
free_table[index].address+=job_length;
free_table[index].length-=job_length;
}
else
{
for(i=index;i<free_number-1;i++)
free_table[i]=free_table[i+1];
free_number--;
}
cout<<"内存分配成功!"<<endl;
}
void show(){
int i;
cout<<endl<<"______________________________"<<endl;
cout<<"当前空闲表"<<endl;
cout<<"起始地址 长度 "<<endl;
for(i=0; i<free_number;i++){
cout.width(6);
cout<<free_table[i].address;
cout.width(8);
cout<<free_table[i].length<<endl;
}
cout<<endl<<"_______________________________"<<endl;
cout<<"当前已分配表:"<<endl;
cout<<"起始地址 长度 作业标签"<<endl;
for(i=0; i<used_number;i++){
cout.width(6);
cout<<used_table[i].address;
cout.width(6);
cout<<used_table[i].length;
cout. width(6);
cout<<used_table[i].name<<endl;
}
}
void free(int address,int length)
{
free_number++;
for(int i=0;i<free_number;i++)
{
if(i==0&&free_table[i].address>address)
{
for(int j=free_number-1;j>0;j--)
free_table[j]=free_table[j-1];
free_table[0].address=address;
free_table[0].length=length;
}
if(i==free_number-1&&free_table[i].address<address)
{
free_table[free_number-1].address=address;
free_table[free_number-1].length=length;
}
if(free_table[i].address<address&&free_table[i+1].address>address)
{
for(int j=free_number-1;j>i+1;j--)
free_table[j]=free_table[j-1];
free_table[i+1].address=address;
free_table[i+1].length=length;
}
}
}
void recover()
{
int job_name,index=-1,address,length;
cout<<"请输入待回收的作业名:"<<endl;
scanf("%d",&job_name);
for(int i=0;i<used_number;i++)
{
if(used_table[i].name==job_name)
{
index=i;
break;
}
}
if(index==-1)
{
cout<<"回收失败!没有这个作业!"<<endl;
return ;
}
else
{
address=used_table[index].address;
length=used_table[index].length;
int flag1=-1;
int flag2=-1;
for(int j=index;j<used_number-1;j++)
used_table[j]=used_table[j+1];
used_number--;
for(int i=0;i<free_number;i++)
{
if(free_table[i].address+free_table[i].length==address)
{
free_table[i].length+=length;
flag1=i;
}
if(free_table[i].address==address+length)
{
flag2=1;
if(flag1>=0){
free_table[flag1].length+=free_table[i].length;
for(int j=i;j<free_number-1;j++)
free_table[j]=free_table[j+1];
free_number--;
printf("%d\n",free_number);
}
else{
free_table[i].length+=length;
free_table[i].address=address;
}
}
}
if(flag1==-1&&flag2==-1)
{
free_number++;
int k=find_insert(free_table,free_number,address);
free_table[k].address=address;
free_table[k].length=length;
}
}
cout<<"回收成功!"<<endl;
}
int main()
{
cout<<" 动态分区储存管理模拟系统 "<<endl;
cout<<"---------------------------------------------------------"<<endl;
init();
int choice;
while(true){
cout<<"========================================================="<<endl;
cout<<"1.分配空间 2.回收空间 3.显示空闲表和分配表 4.用户登录 0.退出"<<endl;
cout<<"请输入你的选择"<<endl;
scanf("%d",&choice);
switch(choice){
case 0:
cout<<"感谢使用本系统 再见 ^_^ "<<endl;
return 0;
case 1:
int t;
cout<<"1.first-fit 2.best-fit 3.worst-fit 0.退出"<<endl;
cout<<"请输入想要选择的分配算法:";
scanf("%d",&t);
switch(t){
case 0:
break;
case 1:
first_fit();
break;
case 2:
best_fit();
break;
case 3:
worst_fit();
break;
default:
cout<<"输入的选择错误请重新选择"<<endl;
}
break;
case 2:
recover();
break;
case 3:
show();
break;
case 4:{
cout << "请输入用户名:" << endl;
string username, password;
cout<<"username:";
cin>>username; // 用户名
cout<<"password:";
cin>>password;
// 这里可以添加用户验证逻辑
if (username == expected_username && password == expected_password) {
cout << "用户名:" << username << " 登录成功!" << endl;
} else {
cout << "用户名或密码错误。" << endl;
}
break;
}
default:
cout<<"输入的选择错误请重新选择"<<endl;
}
}
}
-
程序运行结果截图
-
实验遇到问题及解决处理方法
遇到的问题
1.无法正确记录主存的使用情况,内存的分配和回收出错
2.内存使用效率逐渐降低
3.在做好实验之后,想添加一个用户登录界面,结果运行之后发现不论如何都会显示用户名或密码错误
处理方法:
1.经过debug分析发现,是数据结构设计的不合理,可能无法正确记录主存的使用情况,导致内存分配和回收出错。
2.验证之后,发现内存在回收时,相邻的空闲区合并的逻辑实现不正确,可能导致内存的碎片增多,影响内存的使用效率
3.
在我无论是使用C++自带的函数库,还是自己手写一个新的匹配函数时,程序始终是显示用户名或密码错误,这就让我想到了字符串和值的匹配问题,如果加上 “” 引号,那么字符串的匹配就会变成username的值和username这几个字母的匹配问题了
删除引号之后,程序就可以正常执行了
实验心得感悟
实验让我深刻理解了计算机操作系统中内存管理的理论知识,并将其应用于实际编程中。通过编写代码实现内存分配和回收算法,我更加明白了理论在实践中的应用和重要性。
实验中涉及到的首次适应、最佳适应和最差适应算法,让我对这些算法的原理和应用有了更深刻的理解。我学会了如何根据不同场景选择合适的算法,以及如何优化算法以提高效率。
在解决字符串匹配问题时,我意识到了编程中对细节的关注至关重要。一个小小的疏忽,比如引号的使用,都可能导致程序无法正常运行。
内存分配和回收出错,内存使用效率逐渐降低,以及用户登录界面始终显示错误。
实验强化了对内存管理算法的理解,特别是首次适应、最佳适应和最差适应算法的实现和比较。
学会了如何设计数据结构来模拟内存分配和回收的过程,加深了对内存管理策略的认识。
通过解决字符串匹配问题,意识到了编程中对细节的关注至关重要。