项目___模拟实现内存管理系统

版权声明:私藏源代码是违反人性的罪恶行为!博客转载无需告知,学无止境。 https://blog.csdn.net/qq_41822235/article/details/86249875

参考资料内存管理模拟实验

一、项目概述

1.1 理论

空闲分区表数据结构实现动态分区分配,以首次适应算法(First Fit)进行内存的分配。虽然空闲分区表相对于空闲分区链而言更为简单,但是对我们理解现代操作系统的内存分配大有裨益。理解了空闲分区表的思想,空闲分区链一脉相承。

分区号 分区大小 分区始址 状态

            1

50 85 空闲
2 32 155 空闲
3 70 275 空闲
4 60 532

     空闲

5 ... ... ...

1.2 数据结构设计

要描述如上所示的空闲分区表,最好的数据结构就是数组:

typedef struct Item
{
    char *addr;    //分区始址
    int size;    //大小
    int tag;    //标记 0空闲 1占用
}Item;

数组元素就是Item,现定义表格:

typedef struct Table
{
    Item *data;    //数组指针
    int cursize;    //当前元素个数
    int capacity;    //容量
}Table;

将数组定义成指针类型,方便进行扩容。

1.3 API设计

//初始化空闲分区表和已分配分区表
void init();

//根据作业长度找到顺序找到第一个适合该作业的区块,返回区块位置
int findSpace(int &job_length);

//对表进行扩容, incre为扩容倍数
void increCapacity(Table &tb, int incre);

//首次适应算法
void *FirstFit();

//打印输出空闲分区表
void showIdlePartition();

//打印输出已分配分区表
void showUsedPartition();

//撤销分区
void cancel();

//打印输出菜单
void printHint();

//根据输入的选项进行选择
void makeChoice(int choice);

二、C++实现

2.1 区块分配流程

2.2 区块回收流程

本流程主要描述了内存区块回收的四类情况:上邻接、下邻接、上下均邻接、上下均不邻接。

2.3 编程实现

将分配区的首地址返回给调用者是本项目的核心之所在。

必要准备: 

#include<iostream>
#include<string.h>  //memset()
#include<stdio.h> //printf()
#include<malloc.h>
#include<assert.h>  //assert()
using namespace std;

#define CAPACITY 20 //数组容量
#define CURSIZE 10 //已用大小

//描述区块大小的情况
#define INITIALSIZE 10  //初始大小
#define INCREMENT 30    //分区增量

void *place = (void*)malloc(1000);

typedef struct Item
{
    char *addr; //起始地址
    int size;   //空间大小
    int tag;    //标记
}Item;  //表项

typedef struct Table
{
    Item *data;     //在这里之所以设置指针是为了将来扩容的需要
    int cursize;    //当前元素个数
    int capacity;   //容量
}Table; //表结构

Table frees, occupys;   //空闲分区  已分配分区

init函数实现: 

void init()
{
    //初始化空闲分区表
    frees.capacity = CAPACITY;
    frees.cursize = INITIALSIZE;
    frees.data = new Item[frees.capacity];

    assert(NULL != frees.data);

    frees.data[0].addr = (char*)place;
    frees.data[0].size = INITIALSIZE;
    frees.data[0].tag = 0;
    for(int i = 1; i < frees.cursize; ++i)
    {
        frees.data[i].addr = frees.data[i-1].addr + frees.data[i-1].size;
        frees.data[i].size = frees.data[i-1].size + INCREMENT;
        frees.data[i].tag = 0;
    }

    //初始化已分配分区表
    occupys.capacity = CAPACITY;
    occupys.data = new Item[occupys.capacity];

    assert(NULL != occupys.data);

    occupys.cursize = 0;
    memset(occupys.data, 0, occupys.capacity);
}

findSpace实现: 

int findSpace(int &job_length) //找到第一个合适的区块
{
    cout<<"输入作业大小:"<<endl;
    cin>>job_length;
    int pos = -1;   //记录可用的第一个分区的大小
    for(int i = 0; i < frees.cursize; ++i)  //检索是否有合适大小
    {
        if(frees.data[i].size >= job_length)
        {
            pos = i;
            break;
        }
    }
    return pos;
}

increCapacity实现 

void increCapacity(Table &tb, int incre)    //扩容函数
{
    if(incre <= 1)      //扩容函数不实现缩减空间
        return;
    Item *tmp = tb.data;
    tb.data = new Item[incre * tb.capacity];

    assert(NULL != tb.data);
    memset(tb.data, 0, tb.capacity*2);

    for(int i = 0; i < tb.capacity; ++i)
        tb.data[i] = tmp[i];
    delete []tmp;   //释放原有空间避免内存泄漏
    tb.capacity *= incre;
}

首次适应算法 

void* FirstFit()        //首次适应算法
{
    void *res_addr;     //返回申请到的空间的首地址
    int job_length = 0;
    int pos = findSpace(job_length);
    if(pos == -1)
    {
        cout<<"没有可用空间"<<endl;
        return NULL;
    }
    res_addr = (void*)frees.data[pos].addr;
    //没有在if判断时return 说明确实存在可用空间

    //已用分区表已满需扩容
    if(occupys.cursize == occupys.capacity)
    {
        increCapacity(occupys, 2);
    }

    //模拟进行进行分配的过程,注意已用空间数量+1
    occupys.data[occupys.cursize].addr = frees.data[pos].addr;
    occupys.data[occupys.cursize].size = job_length;
    occupys.data[occupys.cursize].tag = 1;
    occupys.cursize++;

    if(frees.data[pos].size > job_length)   //可用分区大小超过申请的大小
    {
        frees.data[pos].addr += job_length; //修改该可用分区始址
        frees.data[pos].size -= job_length; //修改该可用分区大小
    }else   //可用分区的大小恰好等于申请的大小
    {
        for(int j = pos; j < frees.cursize-1; ++j)
            frees.data[j] = frees.data[j+1];
        frees.cursize--;    //可用分区数减1
    }
    cout<<"空间申请成功\n";
    return res_addr;
}

打印输出空闲分区

void showIdlePartition() //打印输出空闲分区表
{
    cout<<"----------------------------------------------------------\n";
    cout<<"当前空闲分区表如下"<<endl;
    cout<<"编号 起始地址 长度      状态  "<<endl;
    for(int i = 0; i < frees.cursize; ++i)
        printf("%-4d%-10p%-10d%-2d\n",i ,frees.data[i].addr, frees.data[i].size, frees.data[i].tag);
    cout<<"----------------------------------------------------------\n";
}

打印输出已用分区 

void showUsedPartition() //打印输出已用分区表
{
    cout<<"----------------------------------------------------------\n";
    cout<<"当前已分配分区表如下"<<endl;
    cout<<"编号 起始地址 长度      状态  "<<endl;
    for(int i = 0; i < occupys.cursize; ++i)
        printf("%-4d%-10p%-10d%-2d\n",i ,occupys.data[i].addr, occupys.data[i].size, occupys.data[i].tag);
    cout<<"----------------------------------------------------------\n";
}

撤销作业 

void cancel()   //撤销作业
{
    cout<<"请输入回收区的编号"<<endl;
    int num;
    cin>>num;
    if(num < 0 || num >= occupys.capacity)
    {
        cout<<"输入错误,返回"<<endl;
        return;
    }

    //取出待回收的区块
    Item finish = occupys.data[num];
    int i;
    for(i = num; i < occupys.cursize-1;++i)
        occupys.data[i] = occupys.data[i+1];
    occupys.cursize -= 1;

    if(frees.cursize == frees.capacity) //对空闲分区表2倍扩容
        increCapacity(frees,2);

    int pos;   //pos记录插入点前一个
    for(int i = 0; i < frees.capacity; ++i)
    {
        if(frees.data[i].addr+frees.data[i].size <= finish.addr || frees.data[i].size == 0)
        {
            pos = i;
            break;
        }
    }

    if(frees.data[pos].size == 0)   //如果空闲分区表该项未使用直接放入
    {
        frees.data[pos].addr = finish.addr;
        frees.data[pos].size = finish.size;
        frees.data[pos].tag = 0;
        return;
    }

    if(frees.data[pos].addr+frees.data[pos].size == finish.addr)        //满足上邻接
    {
        frees.data[pos].size += finish.size;    //和上空闲区域合并
        if(frees.data[pos+1].addr == finish.addr+finish.size) //满足同时还满足下邻接 表项数会改变
        {
            frees.data[pos].size += frees.data[pos+1].size;
            for(int i = pos+1; i < frees.cursize-1; ++i)
            {
                frees.data[i] = frees.data[i+1];
            }
            frees.cursize--;
        }
    }else   //不满足上邻接
    {
        if(frees.data[pos+1].addr == finish.addr+finish.size)   //满足下邻接
        {
            frees.data[pos+1].addr = finish.addr;
            frees.data[pos+1].size += finish.size;
        }else   //不满足下邻接 表项数改变
        {
            for(int i = frees.cursize-1; i >= pos+1 ; --i)
            {
                frees.data[i+1] = frees.data[i];
            }
            frees.data[pos+1].addr = finish.addr;
            frees.data[pos+1].size = finish.size;
            frees.data[pos+1].tag = 0;
            frees.cursize++;
        }
    }
}

输出提示信息 

void printHint()
{
    printf(" |--------------------------------------------------|\n");
    printf(" |     可变分区存储管理模拟系统            |\n");
    printf(" |--------------------------------------------------|\n");
    printf(" |      菜单:      (0)退出                    |\n");
    printf(" |                                          |\n");
    printf(" |    (1)申请空间     (2)撤消作业              |\n");
    printf(" |                                          |\n");
    printf(" |    (3)显示空闲表    (4)显示分配表            |\n");
    printf(" |--------------------------------------------------|\n");
}

根据用户的选择转调函数 

void makeChoice(int choice) //接受用户的选择
{
    switch(choice)
    {
        case 0:
            break;
        case 1:
            FirstFit();
            break;
        case 2:
            cancel();
            break;
        case 3:
            showIdlePartition();
            break;
        case 4:
            showUsedPartition();
            break;
        default:
            break;
    }
}

main主函数 

int main()
{
    init(); //初始化空闲分区表
    printHint();    //打印输出提示信息
    while(1)
    {
        int choice;
        cout<<"请选择 0(退出) 1(申请空间) 2(撤销作业) 3(显示空闲表) 4(显示分配表):";
        fflush(stdout);
        cin>>choice;
        if(choice < 0 || choice > 4)
        {
            cout<<"请重新选择"<<endl;
            continue;   //结束本次循环
        }
        if(0 == choice) //结束man主函数
        {
            delete []frees.data;
            delete []occupys.data;
            return 0;
        }
        makeChoice(choice);     //根据用户的输入做出选择
    }

    return 0;
}

2.4 运行结果

申请空间 

回收空间 

猜你喜欢

转载自blog.csdn.net/qq_41822235/article/details/86249875