操作系统:可变分区管理实现内存的动态申请与释放(含代码)
固定分区存储管理将内存空间划分为若干个位置和大小固定的分区。可变分区存储管理不会预先划分内存分区,而是在进程装入内存时根据进程大小动态地建立分区。也就是说,最开始的时候,内存就只有一个大分区(假设这个分区大小为1000)。当一个新作业要求装入时,必须找到一个足够大的空闲区。如果找到的空闲分区大小等于作业需要的大小,则把该空闲分区分配给作业。如果找到的空闲分区大小大于作业需要的大小,则把该空闲分区分
以可变分区管理实现内存的动态申请与释放,限定最大分区数和存储空间大小,每次操作后显示分区信息。当申请内存时,从中选取满足要求的空闲区,并划出一个分区;当不满足要求或超出分区数限制时,提示分配失败;当释放内存时,回收相应内存区,并合并成一个新的空闲区。
1、原理说明
固定分区存储管理将内存空间划分为若干个位置和大小固定的分区。
可变分区存储管理不会预先划分内存分区,而是在进程装入内存时根据进程大小动态地建立分区。
也就是说,最开始的时候,内存就只有一个大分区(假设这个分区大小为1000)。
当一个新作业要求装入时,必须找到一个足够大的空闲区。
如果找到的空闲分区大小等于作业需要的大小,则把该空闲分区分配给作业。
如果找到的空闲分区大小大于作业需要的大小,则把该空闲分区分成两部分,一部分分配给作业,另一部分作为一个较小的空闲分区登记下来以备分配。
如下图所示,假如一个新作业需要大小为400的空间,第一个空闲分区太小了装不下,第二个空闲区足够大可以装下,且多出来的100大小的空间,那么多出来的部分作为一个新的空闲分区。
当一个作业运行结束时,它所归还的分区如果与其他空闲分区相邻,则要进行合并,形成一个大的空闲分区。
如下图所示,第二个作业运行结束时,它将变成空闲分区,且它的上方还有一个空闲分区,此时他们应该合并为一个大的空闲分区。
2、代码说明
代码使用链表的形式连接各个分区
选择空闲分区使用的是“首次适应算法”,即从链首顺序查找,找到第一个满足要求的分区即可开始分配。
下面是申请内存和释放内存的机制。
①申请内存
②释放内存
3、运行结果
运行结果我给出了多种情况,所以有点多,而且中间为了达到演示状态所进行的申请释放过程有所省略。
1、申请内存,选择第一个满足要求的空闲区,并划分分区
czxt2022@ubuntu:~$ gcc 3.c -o 3
czxt2022@ubuntu:~$ ./3
请输入最大分区数和存储空间大小:
10
1000
…中间有省略…
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 true
1 100 100 false
2 200 800 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
1
请输入你想要申请多大的分区:
200
分配成功!此次申请了大小为200的内存!
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 true
1 100 100 false
2 200 200 false
3 400 600 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
3
成功退出!
2、申请内存,但没有满足要求的空闲分区
czxt2022@ubuntu:~$ ./3
请输入最大分区数和存储空间大小:
10
1000
…中间有省略…
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 false
1 100 200 true
2 300 50 false
3 350 500 false
4 850 150 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
1
请输入你想要申请多大的分区:
500
没有满足要求的空闲分区了,分配失败!
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
3
成功退出!
3、申请内存,但现有分区数已经是最大分区数
czxt2022@ubuntu:~$ ./3
请输入最大分区数和存储空间大小:
5
1000
…中间有省略…
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 false
1 100 50 true
2 150 300 false
3 450 100 false
4 550 450 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
1
超出分区数限制,分配失败!
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
3
成功退出!
4、释放内存,回收内存
czxt2022@ubuntu:~$ ./3
请输入最大分区数和存储空间大小:
10
1000
…中间有省略…
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 false
1 100 200 false
2 300 300 false
3 600 400 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
2
请输入你要释放的分区编号:
1
回收成功!此次回收了大小为200的内存!
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 false
1 100 200 true
2 300 300 false
3 600 400 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
3
成功退出!
5、释放内存,回收内存,合并相邻空闲分区
czxt2022@ubuntu:~$ ./3
请输入最大分区数和存储空间大小:
10
1000
…中间有省略…
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 true
1 100 50 false
2 150 150 true
3 300 300 false
4 600 400 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
2
请输入你要释放的分区编号:
1
回收成功!此次回收了大小为50的内存!
--------------------------------------------------
编号 始址 大小 空闲
0 0 300 true
1 300 300 false
2 600 400 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
3
成功退出!
6、释放内存,但编号错误
czxt2022@ubuntu:~$ ./3
请输入最大分区数和存储空间大小:
10
1000
…中间有省略…
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 false
1 100 200 false
2 300 300 false
3 600 400 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
2
请输入你要释放的分区编号:
5
没有此编号!
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
3
成功退出!
7、释放内存,但本来就是空闲分区
czxt2022@ubuntu:~$ ./3
请输入最大分区数和存储空间大小:
10
1000
…中间有省略…
--------------------------------------------------
编号 始址 大小 空闲
0 0 100 false
1 100 200 false
2 300 300 false
3 600 400 true
--------------------------------------------------
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
2
请输入你要释放的分区编号:
3
此分区本来就是空闲的,无需释放!
请输入操作编号:
1、申请内存
2、释放内存
3、清空退出
3
成功退出!
4、源代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define true 1
#define false 0
int MAX_PARTITION_NUM;//最大
int STORAGE_SAPACE_SIZE;//存储空间大小
int PARTITION_NUM=1;//分区数
typedef struct partition//分区节点
{
int size;//分区大小
int head;//分区始址
int free;//分区状态(是否空闲)
struct partition* next;//指向下一个分区
}Partition;
Partition* start;//首节点,指向第一个分区
Partition* end;//尾节点,最后一个分区指向它
void ShowView()//显示分区信息
{
printf("--------------------------------------------------\n");
printf("编号\t始址\t大小\t空闲\n");
Partition* par;
par=start->next;
int i=0;
char msg[10];
for(;par!=end;par=par->next,i++)
{
if(par->free==true)strcpy(msg,"true");
else strcpy(msg,"false");
printf("%d\t%d\t%d\t%s\n",i,par->head,par->size,msg);
}
printf("--------------------------------------------------\n");
}
void apply()//申请内存
{
if(PARTITION_NUM==MAX_PARTITION_NUM)
{//现有分区数如果已经等于最大限制,那就不应该再分配了
printf("超出分区数限制,分配失败!\n");
return;
}
printf("请输入你想要申请多大的分区:\n");
int aSzie;
scanf("%d",&aSzie);
int i=1;
Partition* par=start;
for(;par->next!=end;par=par->next)
{
Partition* left=par;
Partition* right=par->next;
if(right->size>=aSzie&&right->free==true)
{//如果找到一个大小满足要求且为空闲的分区,即可开始分配
Partition* one=(Partition*)malloc(sizeof(Partition));
one->size=aSzie;
one->head=right->head;
one->free=false;//被分配走的空闲分区不空闲
right->size=right->size-aSzie;//被分走后的大小
right->head=one->head+one->size;//被分走后的始址
one->next=right;
left->next=one;
PARTITION_NUM++;//每分配一个分区,分区数+1
printf("分配成功!此次申请了大小为%d的内存!\n",aSzie);
ShowView();
return;
}
}
//循环遍历每个分区都没有找到满足要求的分区
printf("没有满足要求的空闲分区了,分配失败!\n");
}
void release()
{
printf("请输入你要释放的分区编号:\n");
int aNum;
scanf("%d",&aNum);
Partition* par=start;
Partition* left;
int i=0;
while(i<aNum+1)
{//循环到第aNum个分区
left=par;
par=par->next;
if(par==end)
{//循环到最后都没有找到
printf("没有此编号!\n");
return;
}
i++;
}
if(par->free==true)
{//如果该分区为空闲分区
printf("此分区本来就是空闲的,无需释放!\n");
return;
}
else
{
printf("回收成功!此次回收了大小为%d的内存!\n",par->size);
if(aNum==0&&par->next==end||aNum==0&&par->next->free==false||par->next==end&&left->free==false||left->free==false&&par->next->free==false)
{//回收
par->free=true;
}
else if(par->next==end&&left->free==true||left->free==true&&par->next->free==false)
{//回收+左空闲
left->size=left->size+par->size;
left->next=par->next;
PARTITION_NUM--;//合并两个空闲分区,分区数-1
free(par);
}
else if(aNum==0&&par->next->free==true||left->free==false&&par->next->free==true)
{//回收+右空闲
par->size=par->size+par->next->size;
par->free=true;
Partition* useless=par->next;
par->next=par->next->next;
PARTITION_NUM--;//合并两个空闲分区,分区数-1
free(useless);
}
else
{//回收+左空闲+右空闲
left->size=left->size+par->size+par->next->size;
left->next=par->next->next;
PARTITION_NUM-=2;//合并三个空闲分区,分区数-2
free(par->next);
free(par);
}
}
ShowView();
}
void quit()
{//清空分区
Partition* par;
while (start->next!=end)
{
par=start->next;
start->next=par->next;
free(par);
}
}
int main()
{
printf("请输入最大分区数和存储空间大小:\n");
scanf("%d%d",&MAX_PARTITION_NUM,&STORAGE_SAPACE_SIZE);
//初始化
Partition* one=(Partition*)malloc(sizeof(Partition));
start=(Partition*)malloc(sizeof(Partition));
end=(Partition*)malloc(sizeof(Partition));
one->size=STORAGE_SAPACE_SIZE;
one->head=0;
one->free=true;
one->next=end;
start->next=one;
ShowView();
while(1)
{
printf("请输入操作编号:\n1、申请内存\n2、释放内存\n3、清空退出\n");
int choice;
scanf("%d",&choice);
if(choice==1)
{//申请内存
apply();
}
else if(choice==2)
{//释放内存
release();
}
else if(choice==3)
{//清空退出
quit();
break;
}
else
{
printf("你输入的编号有误,请重新输入!\n");
}
}
printf("成功退出!\n");
system("pause");
return 0;
}
更多推荐
所有评论(0)