操作系统:可变分区管理实现内存的动态申请与释放(含代码)


以可变分区管理实现内存的动态申请与释放,限定最大分区数和存储空间大小,每次操作后显示分区信息。当申请内存时,从中选取满足要求的空闲区,并划出一个分区;当不满足要求或超出分区数限制时,提示分配失败;当释放内存时,回收相应内存区,并合并成一个新的空闲区。


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;	
}


猜你喜欢

转载自blog.csdn.net/qq_45750767/article/details/125467326
今日推荐