一、实验目的
1、了解操作系统动态分区存储管理过程和方法。
2、掌握动态分区存储管理的主要数据结构--空闲表区。
3、加深理解动态分区存储管理中内存的分配和回收。
4、掌握空闲区表中空闲区3种不同放置策略的基本思想和实现过程。
5、通过模拟程序实现动态分区存储管理。
6、了解请求分页虚拟存储管理技术的方法和特点。
7、通过模拟实现请求页式存储管理的几种基本页面置换算法。
8、掌握页面置换算法种缺页率、置换率和命中率的计算方法。
二、实验内容
1、编程模拟实现动态分区管理中内存的分配和回收及空闲区表的管理。(2分)
首次适应算法(First Fit)参考程序:
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#define N 5
struct freearea
{
int startaddr; //空闲区起始地址
int size; //空闲区大小
int state; //1表示空闲,0表示占用
}freeblock[N]={{20,20,1},{80,50,1},{150,100,1},{300,30,1},{600,100,1}};
int alloc(int size)
{
int i,tag=0,allocaddr;
for(i=0;i<N;i++)
{
if(freeblock[i].state==1 && freeblock[i].size>size) //申请空间小于空闲空间
{
allocaddr=freeblock[i].startaddr; //作业地址
freeblock[i].startaddr+=size; //新空闲区起始地址
freeblock[i].size-=size; //新空闲区大小
tag=1; //分配标记
break;
}
else if(freeblock[i].state==1 && freeblock[i].size==size)//申请空间正好等于空闲空间
{
allocaddr=freeblock[i].startaddr;
freeblock[i].state=0;tag=1;
break;
}
}
if(tag==0) //表示没找到合适的空闲区,未分配内存
allocaddr=-1;
return allocaddr; //返回作业地址
}
void setfree(int addr,int size) //传过来的参数是要释放内存的起始地址和大小
{
int i,tag1=0,tag2=0,n1=0,n2=0;
for(i=0;i<N;i++)
{
if(freeblock[i].startaddr+freeblock[i].size==addr && freeblock[i].state==1)
{
tag1=1; //有上邻标记
n1=i; //记录上邻数组位置(分区号)
break;
}
}
for(i=0;i<N;i++)
{
if(freeblock[i].startaddr==addr+size && freeblock[i].state==1)
{
tag2=1; //有下邻标记
n2=i; //记录下邻数组位置(分区号)
break;
}
}
if(tag1==1 && tag2==0) //有上邻无下邻
{
freeblock[n1].size+=size;
}
else if(tag1==1 && tag2==1) //有上邻有下邻
{
freeblock[n1].size+=freeblock[n2].size+size;
freeblock[n2].state=0;//???
}
else if(tag1==0 && tag2==1) //无上邻有下邻
{
freeblock[n2].startaddr=addr;
freeblock[n2].size+=size;
}
else //无上邻无下邻(表明空间正好全部分配出去,空间的状态为0)
{
for(i=0;i<N;i++)
{
if(freeblock[i].state==0) //通过空间状态值找到这块空间
{
freeblock[i].startaddr=addr;
freeblock[i].size=size;
freeblock[i].state=1;
break;
}
}
}
}
void adjust()
{
int i,j;
struct freearea temp;
for(i=1;i<N;i++) //依据首次适应算法将空闲区按起始地址由低到高冒泡排序
{
for(j=0;j<N-i;j++)
{
if(freeblock[j].startaddr>freeblock[j+1].startaddr)
{
temp=freeblock[j];
freeblock[j]=freeblock[j+1];
freeblock[j+1]=temp;
}
}
}
for(i=1;i<N;i++) //把状态为0的排到后面
{
for(j=0;j<N-i;j++)
{
if(freeblock[j].state==0 && freeblock[j+1].state==1)
{
temp=freeblock[j];
freeblock[j]=freeblock[j+1];
freeblock[j+1]=temp;
}
}
}
}
void print()
{
int i;
printf("\t|-------------------------------|\n");
printf("\t|startaddr size state |\n");
for(i=0;i<N;i++)
printf("\t|%4d %4d %4d |\n",freeblock[i].startaddr,freeblock[i].size,freeblock[i].state);
}
int main()
{
int size,addr;
char c1,c2,c;
printf("At first the free memory is this:\n");//首先,空闲区是这样的
adjust();
print();
printf("Is there any job request memory?(y or n):");//有作业需要申请内存么?
while((c1=getchar())=='y')
{
printf("Input request memory size:"); //输入所需内存大小
scanf("%d",&size);
addr=alloc(size); //调用内存分配函数,返回的是作业的起始地址
if(addr==-1)
printf("There is no fit memory.Please wait!!!\n");
else
{
printf("Job's memory start address is:%d\n",addr); //输出作业的起始地址
printf("Job's size is:%d\n",size); //输出作业大小
printf("After allocation the free memory is this:\n"); //分配后可用内存如下: adjust();
print();
printf("Job is running.\n");
}
getchar();
printf("Is there any memory for free?(y or n):");//有需要释放的内存么?
while((c2=getchar())=='y')
{
printf("Input free area startaddress:");
scanf("%d",&addr); //输入要释放内存的起始地址
printf("Input free area size:");
scanf("%d",&size); //输入要释放内存的大小
setfree(addr,size); //调用释放内存函数
adjust();
print();
getchar();
printf("Is there any memory for free?(y or n):");
}
getchar();
printf("Is there any job request memory?(y or n):");
}
return 0;
}
运行结果截屏(包含分配和回收两部分):
分析该程序,列出各模块实现的功能:
1)alloc()
alloc() 函数为作业请求分配内存空间,从预定义的空闲内存块中找到合适的块并进行分配。
当程序检测到有作业请求内存时,通过调用 alloc(size) 函数来尝试分配指定大小 size 的内存空间。
alloc() 函数会遍历预定义的空闲内存块列表 freeblock[N],寻找第一个满足条件的空闲块:
空闲状态为 1(表示可用)。
大小大于或等于请求的 size。
如果找到合适的空闲块,alloc() 函数将更新该空闲块的状态和大小,标记为已分配(state = 0),并返回分配的作业内存块的起始地址。
如果无法找到满足请求的合适空闲块(即所有空闲块都无法容纳该作业),则 alloc() 函数返回 -1,表示分配失败。
alloc() 函数是整个内存管理系统中的核心部分,负责有效地管理和分配可用内存块。
它实现了简单的首次适应(first-fit)算法,根据作业的内存请求,将空闲块分配给作业,以满足程序的内存需求。
在主程序中,当作业请求内存时,会调用 alloc() 函数进行内存分配,并根据分配的结果执行相应的处理逻辑(如打印分配结果、更新空闲内存块列表等)。
alloc() 函数的返回值决定了作业请求内存的成功与否,从而影响程序的后续流程和作业的执行状态。
2)setfree()
setfree() 函数释放已占用的内存块,将其重新标记为可用的空闲内存块,并进行必要的空闲内存块合并操作。
当程序检测到作业不再需要某块内存时(例如作业执行完毕),会调用 setfree(addr, size) 函数来释放该作业占用的内存空间。
addr 参数表示要释放的内存块的起始地址,size 参数表示要释放的内存块的大小。
setfree() 函数首先会查找要释放的内存块是否与其他空闲内存块相邻,从而决定如何合并空闲块或创建新的空闲块。
通过遍历空闲内存块列表 freeblock[N],检查是否存在相邻的空闲块,以确定合并的方式。
如果要释放的内存块与某个空闲块相邻(上下邻接),则 setfree() 函数会将这些相邻的空闲块合并为一个更大的空闲块。
这样可以最大程度地利用内存空间,减少碎片化。
根据释放的内存块位置和大小,更新空闲块列表 freeblock[N] 中对应块的状态和大小。
将原来被占用的内存块重新标记为可用的空闲块(state = 1)。
在合并或释放后,可能会导致空闲块列表 freeblock[N] 中的顺序发生变化,因此需要调用 adjust() 函数对空闲块列表进行重新排序和调整,以便后续的内存分配能够高效地找到合适的空闲块。
3) adjust()
adjust() 函数对空闲内存块列表 freeblock[N] 进行调整和排序,以确保空闲内存块按照一定的规则进行管理和利用。
adjust() 函数实现了对空闲内存块的排序功能,将空闲块按照起始地址从小到大的顺序进行排列。
通过使用冒泡排序算法或类似的方法,将空闲内存块列表 freeblock[N] 中的元素按照起始地址升序进行排列,以便后续的内存分配和管理能够更高效地进行。
在排序的过程中,adjust() 函数也会根据空闲块的状态进行调整,确保已分配的内存块(state = 0)排在未分配的内存块(state = 1)之后。
这样可以提高内存分配算法的效率,例如首次适应算法(first-fit),从而更快地找到合适的空闲块来满足作业的内存需求。
adjust() 函数可能会通过合并相邻的空闲块来减少内存碎片化,使得空闲内存块更加紧凑和连续。
这样可以提高内存利用率,减少因内存碎片而导致无法分配大内存块的情况,从而优化内存资源的管理和利用。
在程序运行过程中,空闲内存块的状态会不断发生变化(分配、释放),因此需要定期调用 adjust() 函数对空闲内存块列表进行更新和调整,以保持其正确的顺序和状态。
这样可以确保内存分配算法能够在正确的基础上进行,提高系统的性能和稳定性。
2.修改上题,用最佳适应算法和最坏适应算法模拟内存空间的分配和回收。(4分)
注:只需列出程序不同部分,无需将整个程序列出。
(1)最佳适应算法
int alloc(int size)
{
int i, tag = 0, allocaddr = -1;
int min_size = INT_MAX; // 记录最小空闲区大小
int best_fit_index = -1; // 记录最佳适配的空闲区索引
for (i = 0; i < N; i++)
{
if (freeblock[i].state == 1 && freeblock[i].size >= size)
{
if (freeblock[i].size < min_size) // 找到更小的合适空闲区
{
min_size = freeblock[i].size;
best_fit_index = i;
}
}
}
if (best_fit_index != -1)
{
allocaddr = freeblock[best_fit_index].startaddr; // 作业地址
if (freeblock[best_fit_index].size > size) // 空闲区大于请求大小
{
freeblock[best_fit_index].startaddr += size; // 新空闲区起始地址
freeblock[best_fit_index].size -= size; // 新空闲区大小
}
else // 空闲区大小等于请求大小
{
freeblock[best_fit_index].state = 0; // 标记为占用
}
tag = 1; // 分配标记
}
return allocaddr; // 返回作业地址或-1(未分配)
}
(2)最坏适应算法
int alloc(int size)
{
int i, tag = 0, allocaddr = -1;
int max_size = -1; // 记录最大空闲区大小
int worst_fit_index = -1; // 记录最坏适配的空闲区索引
for (i = 0; i < N; i++)
{
if (freeblock[i].state == 1 && freeblock[i].size >= size)
{
if (freeblock[i].size > max_size) // 找到更大的合适空闲区
{
max_size = freeblock[i].size;
worst_fit_index = i;
}
}
}
if (worst_fit_index != -1)
{
allocaddr = freeblock[worst_fit_index].startaddr; // 作业地址
if (freeblock[worst_fit_index].size > size) // 空闲区大于请求大小
{
freeblock[worst_fit_index].startaddr += size; // 新空闲区起始地址
freeblock[worst_fit_index].size -= size; // 新空闲区大小
}
else // 空闲区大小等于请求大小
{
freeblock[worst_fit_index].state = 0; // 标记为占用
}
tag = 1; // 分配标记
}
return allocaddr; // 返回作业地址或-1(未分配)
}
3.编写程序实现先进先出页面置换算法,并计算缺页次数,缺页率,置换次数和命中率。(2分)
参考程序:
#include <stdio.h>
//初始化内存队列
void initializeList(int list[],int number){
int i;
for (i = 0; i < number; i ++) {
list[i] = -1;
}
}
//展示要访问页面号数组
void showList(int list[], int number){
int i;
for (i = 0; i < number; i ++) {
printf("%2d",list[i]);
}
printf("\n");
}
//展示当前内存状态
void showMemoryList(int list[],int phyBlockNum){
int i;
for (i = 0; i < phyBlockNum; i ++) {
if (list[i] == -1) {
break;
}
printf(" |%d|",list[i]);
}
printf("\n");
}
//计算各项指标
void informationCount(int missingCount,int replaceCount,int pageNum){
printf("缺页次数:%d 缺页率:%d/%d\n",missingCount,missingCount,pageNum);
double result = (double)(pageNum - missingCount)/(double)pageNum;
printf("置换次数:%d 命中率:%.2f\n",replaceCount,result);
}
//先进先出置换算法
void replacePageByFIFO(int memoryList[],int phyNum,int strList[],int pageNum){
//置换次数
int replaceCount = 0;
//缺页次数
int missingCount = 0;
//记录当前最早进入内存的下标
int pointer = 0;
//记录当前页面的访问情况: 0 未访问
int i,j,isVisited = 0;
for (i = 0; i < pageNum; i ++) {
isVisited = 0;
//判断是否需要置换->内存已满且需要访问的页面不在内存中
for (j = 0; j < phyNum; j ++) {
if (memoryList[j] == strList[i]) {
//该页面已经存在内存中
//修改访问情况
isVisited = 1;
//展示
printf("%d\n",strList[i]);
break;
}
if (memoryList[j] == -1) {
//页面不在内存中且内存未满->直接存入
memoryList[j] = strList[i];
//修改访问情况
isVisited = 1;
missingCount ++;
//展示
printf("%d\n",strList[i]);
showMemoryList(memoryList, phyNum);
break;
}
}
if (!isVisited) {
//当前页面还未被访问过->需要进行页面置换
//直接把这个页面存到所记录的下标中
memoryList[pointer] = strList[i];
//下标指向下一个
pointer ++;
//如果到了最后一个,将下标归零
if (pointer > phyNum-1) {
pointer = 0;
}
missingCount ++;
replaceCount ++;
//展示
printf("%d\n",strList[i]);
showMemoryList(memoryList, phyNum);
}
}
informationCount(missingCount, replaceCount, pageNum);//计算各项指标
}
int main(int argc, const char * argv[]) {
//物理块的数量
int phyBlockNum;
printf("请输入物理块数量:\n");
scanf("%d",&phyBlockNum);
//生成内存队列数组
int memoryList[phyBlockNum];
//初始化内存状态
initializeList(memoryList, phyBlockNum);
//showMemoryList(memoryList,phyBlockNum);
//页面数量
int pageNum;
printf("请输入要访问的页面总数:\n");
scanf("%d",&pageNum);
//保存页面号数组
int pageNumStrList[pageNum];
int i;
//将要访问的页面号存入数组中
printf("请输入要访问的页面号:\n");
for (i = 0; i < pageNum; i ++) {
scanf("%d",&pageNumStrList[i]);
}
//显示要访问页面号数组中内容
showList(pageNumStrList, pageNum);
int chose;
while (1) {
printf("请选择所需的置换算法:\n");
printf("1.FIFO 2.退出\n");
scanf("%d",&chose);
switch (chose) {
case 1:
//显示要访问页面号数组中内容
showList(pageNumStrList, pageNum);
//调用先进先出置换算法
replacePageByFIFO(memoryList, phyBlockNum, pageNumStrList, pageNum);
//重新初始化内存
initializeList(memoryList , phyBlockNum);
break;
default:
return 0;
break;
}
}
return 0;
}
编译及执行过程以及结果截屏:
分析程序功能:
这段程序是一个模拟页面置换算法(以 FIFO 算法为例)的简单内存管理系统。初始化内存队列
initializeList() 函数用于初始化内存队列 memoryList,将其所有元素都设置为 -1,表示内存块为空闲状态。
展示要访问页面号数组
showList() 函数用于展示要访问的页面号数组 pageNumStrList 中的内容。
展示当前内存状态
showMemoryList() 函数用于展示当前内存队列 memoryList 的状态,即展示内存中存储的页面号。
计算各项指标
informationCount() 函数用于根据缺页次数和置换次数计算缺页率和命中率,并将计算结果输出。
先进先出置换算法
replacePageByFIFO() 函数实现了先进先出(FIFO)页面置换算法:
使用循环遍历要访问的页面号数组 pageNumStrList。
判断页面是否在内存中:
如果页面已经在内存中,表示发生了页面命中。
如果页面不在内存中,需要进行页面置换:
将页面存入当前最早进入内存的位置,并将指针指向下一个位置(如果到达内存队列末尾则循环回到开头)。
计算缺页次数和置换次数,并展示内存状态。
主函数 main()
主函数负责用户交互和调用置换算法:
获取用户输入的物理块数量和要访问的页面号数组。
循环显示页面号数组和提供置换算法选择菜单。
根据用户选择调用相应的页面置换算法,并在每次置换后重新初始化内存状态。
该程序可以通过用户输入物理块数量、要访问的页面号数组和选择置换算法来模拟内存管理过程,并计算出缺页率和命中率等指标,用于简单地展示页面置换算法的工作原理和效果。
4.编程实现其它页面置换算法(如最近最久未使用算法或最佳置换算法等),计算缺页次数,缺页率,置换次数和命中率。(1分)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_PHYSICAL_BLOCKS 10
// 初始化内存状态
void initializeMemory(int memoryList[], int phyBlockNum) {
int i;
for (i = 0; i < phyBlockNum; i++) {
memoryList[i] = -1; // -1 表示内存块为空闲
}
}
// 打印要访问的页面号数组
void showPageList(int pageNumStrList[], int pageNum) {
printf("要访问的页面号序列:");
for (int i = 0; i < pageNum; i++) {
printf("%2d", pageNumStrList[i]);
}
printf("\n");
}
// 打印当前内存状态
void showMemoryList(int memoryList[], int phyBlockNum) {
printf("当前内存状态:");
for (int i = 0; i < phyBlockNum; i++) {
if (memoryList[i] == -1) {
printf("| |");
} else {
printf("|%2d|", memoryList[i]);
}
}
printf("\n");
}
// 计算缺页次数、缺页率、置换次数和命中率
void calculateMetrics(int missingCount, int replaceCount, int pageNum) {
printf("缺页次数:%d 缺页率:%d/%d\n", missingCount, missingCount, pageNum);
double hitRate = (double)(pageNum - missingCount) / (double)pageNum * 100.0;
printf("置换次数:%d 命中率:%.2f%%\n", replaceCount, hitRate);
}
// LRU页面置换算法
void replacePageByLRU(int memoryList[], int phyNum, int strList[], int pageNum) {
int missingCount = 0;
int replaceCount = -phyNum;
int counter[MAX_PHYSICAL_BLOCKS] = {0}; // 访问计数器数组,初始化为0
for (int i = 0; i < pageNum; i++) {
int page = strList[i];
bool pageFound = false;
// 查找页面是否在物理内存中
for (int j = 0; j < phyNum; j++) {
if (memoryList[j] == page) {
pageFound = true;
counter[j] = i + 1; // 更新访问计数器为当前访问的位置,+1避免计数器为0的情况
printf("%d\n", page);
break;
}
}
if (!pageFound) {
missingCount++; // 缺页
// 查找最久未使用的页面进行置换
int replaceIndex = 0;
int minCounter = counter[0];
for (int j = 1; j < phyNum; j++) {
if (counter[j] < minCounter) {
minCounter = counter[j];
replaceIndex = j;
}
}
// 置换页面
memoryList[replaceIndex] = page;
counter[replaceIndex] = i + 1; // 更新计数器
replaceCount++;
printf("%d\n", page);
showMemoryList(memoryList, phyNum);
}
}
calculateMetrics(missingCount, replaceCount, pageNum); // 计算缺页次数、缺页率、置换次数和命中率
}
int main() {
int phyBlockNum;
printf("请输入物理块数量:\n");
scanf("%d", &phyBlockNum);
int memoryList[MAX_PHYSICAL_BLOCKS];
initializeMemory(memoryList, phyBlockNum);
int pageNum;
printf("请输入要访问的页面总数:\n");
scanf("%d", &pageNum);
int pageNumStrList[pageNum];
printf("请输入要访问的页面号:\n");
for (int i = 0; i < pageNum; i++) {
scanf("%d", &pageNumStrList[i]);
}
showPageList(pageNumStrList, pageNum);
int choice;
while (1) {
printf("请选择页面置换算法:\n");
printf("1. LRU算法\n");
printf("2. 退出\n");
scanf("%d", &choice);
switch (choice) {
case 1:
showPageList(pageNumStrList, pageNum);
replacePageByLRU(memoryList, phyBlockNum, pageNumStrList, pageNum);
initializeMemory(memoryList, phyBlockNum); // 重置内存状态
break;
default:
return 0;
}
}
return 0;
}
5.编程用动态分区链形式模拟动态分区管理中内存的分配和回收,采用3种算法(首次适应算法,最佳适应算法,最坏适应算法)实现。(附加题)
#include <stdio.h>
#include <stdlib.h>
#define N 5
// 定义空闲区结构体
struct FreeArea {
int startAddr; // 空闲区起始地址
int size; // 空闲区大小
int state; // 1表示空闲,0表示占用
};
// 初始的空闲区列表
struct FreeArea freeBlock[N] = {
{20, 20, 1},
{80, 50, 1},
{150, 100, 1},
{300, 30, 1},
{600, 100, 1}
};
// 首次适应算法分配内存
int firstFit(int size) {
int i, allocAddr = -1;
for (i = 0; i < N; i++) {
if (freeBlock[i].state == 1 && freeBlock[i].size >= size) {
allocAddr = freeBlock[i].startAddr;
if (freeBlock[i].size == size) {
freeBlock[i].state = 0; // 分配整个空闲区
} else {
freeBlock[i].startAddr += size;
freeBlock[i].size -= size;
}
break;
}
}
return allocAddr;
}
// 最佳适应算法分配内存
int bestFit(int size) {
int i, bestIndex = -1, minSize = 9999999;
for (i = 0; i < N; i++) {
if (freeBlock[i].state == 1 && freeBlock[i].size >= size) {
if (freeBlock[i].size < minSize) {
minSize = freeBlock[i].size;
bestIndex = i;
}
}
}
if (bestIndex != -1) {
int allocAddr = freeBlock[bestIndex].startAddr;
if (freeBlock[bestIndex].size == size) {
freeBlock[bestIndex].state = 0; // 分配整个空闲区
} else {
freeBlock[bestIndex].startAddr += size;
freeBlock[bestIndex].size -= size;
}
return allocAddr;
}
return -1;
}
// 最坏适应算法分配内存
int worstFit(int size) {
int i, worstIndex = -1, maxSize = -1;
for (i = 0; i < N; i++) {
if (freeBlock[i].state == 1 && freeBlock[i].size >= size) {
if (freeBlock[i].size > maxSize) {
maxSize = freeBlock[i].size;
worstIndex = i;
}
}
}
if (worstIndex != -1) {
int allocAddr = freeBlock[worstIndex].startAddr;
if (freeBlock[worstIndex].size == size) {
freeBlock[worstIndex].state = 0; // 分配整个空闲区
} else {
freeBlock[worstIndex].startAddr += size;
freeBlock[worstIndex].size -= size;
}
return allocAddr;
}
return -1;
}
// 释放内存块
void setFree(int addr, int size) {
int i;
for (i = 0; i < N; i++) {
if (freeBlock[i].startAddr + freeBlock[i].size == addr && freeBlock[i].state == 1) {
freeBlock[i].size += size;
break;
}
}
for (i = 0; i < N; i++) {
if (freeBlock[i].startAddr == addr + size && freeBlock[i].state == 1) {
freeBlock[i].startAddr = addr;
freeBlock[i].size += size;
break;
}
}
for (i = 0; i < N; i++) {
if (freeBlock[i].state == 0) {
if (freeBlock[i + 1].state == 1) {
freeBlock[i].size += freeBlock[i + 1].size;
}
}
}
}
// 调整空闲区链表
void adjust() {
int i, j;
struct FreeArea temp;
for (i = 1; i < N; i++) {
for (j = 0; j < N - i; j++) {
if (freeBlock[j].startAddr > freeBlock[j + 1].startAddr) {
temp = freeBlock[j];
freeBlock[j] = freeBlock[j + 1];
freeBlock[j + 1] = temp;
}
}
}
}
// 打印空闲区信息
void print() {
int i;
printf("\t|-------------------------------|\n");
printf("\t|起始地址 大小 状态 |\n");
for (i = 0; i < N; i++) {
printf("\t|%4d %4d %4d |\n", freeBlock[i].startAddr, freeBlock[i].size, freeBlock[i].state);
}
}
int main() {
int size, addr;
char choice;
printf("初始空闲内存状态如下:\n");
adjust();
print();
do {
printf("请选择内存分配算法:\n");
printf("1. 首次适应算法\n");
printf("2. 最佳适应算法\n");
printf("3. 最坏适应算法\n");
printf("4. 退出\n");
printf("请输入选项(1-4):");
scanf(" %c", &choice);
switch (choice) {
case '1':
printf("请输入作业的内存大小:");
scanf("%d", &size);
addr = firstFit(size);
break;
case '2':
printf("请输入作业的内存大小:");
scanf("%d", &size);
addr = bestFit(size);
break;
case '3':
printf("请输入作业的内存大小:");
scanf("%d", &size);
addr = worstFit(size);
break;
case '4':
printf("退出程序。\n");
return 0;
default:
printf("无效的选项,请重新输入。\n");
break;
}
if (choice >= '1' && choice <= '3') {
if (addr == -1) {
printf("无法分配所需内存。\n");
} else {
printf("作业分配的起始地址:%d\n", addr);
printf("分配后的空闲内存状态:\n");
adjust();
print();
// 释放内存
printf("是否需要释放内存?(y或n):");
scanf(" %c", &choice);
while (choice == 'y') {
printf("请输入要释放的区域起始地址和大小:");
scanf("%d %d", &addr, &size);
setFree(addr, size);
adjust();
print();
printf("是否需要继续释放内存?(y或n):");
scanf(" %c", &choice);
}
}
}
} while (choice != '4');
return 0;
}
三、实验总结和体会(1分)
本次学习中,你可以学到以下几个方面:
动态分区管理:学习了如何使用链表来模拟动态分区管理中的内存分配和回收过程。动态分区管理是一种常见的内存管理方式,适用于需要动态分配和回收内存空间的场景,比如操作系统中的内存分配。
内存分配算法:掌握了常见的内存分配算法,包括首次适应算法、最佳适应算法和最坏适应算法。这些算法针对不同的内存分配需求,选择合适的算法可以提高内存利用效率和系统性能。
数据结构与算法:通过实现动态分区管理算法,加深了对链表、循环、条件判断等基本数据结构和算法的理解和应用。
本次实验存在许多难点:
算法的选择和实现:需要理解并实现多种内存分配算法,包括不同算法的逻辑和具体操作步骤。链表的操作:使用链表来管理动态分区,需要熟练掌握链表的插入、删除等操作,确保内存分配和回收的准确性和高效性。用户交互的设计:设计用户友好的交互界面,能够准确捕捉用户的输入,并根据用户选择进行相应的操作和反馈,考验了程序设计的整体性和实用性。