【操作系统】内存分配与回收

该博客介绍了两种内存分配方法——Firstfit和Nextfit,以及相应的内存回收机制。Firstfit策略从空闲分区表的开始寻找合适的空间分配,而Nextfit则从上次分配后的位置开始查找。程序实现了这两种分配法,允许用户分配和回收内存,并显示内存占用情况和空闲分区列表。此外,还提供了计算平均搜索空闲区次数的功能。
摘要由CSDN通过智能技术生成

实现了两种内存分配方法,和内存回收机制

First fit 分配法

在这里插入图片描述

// #include <iomanip>
#include <iostream>
#include<algorithm>
#define M 20
#define N 20
using namespace std;

//假定最大空闲分区20个,内存中同时最多可容纳的作业数20个
struct my_empty//空闲分区表
{
    int address_of_start; //起始地址
    int size_of_empty; //空闲大小,依据分配单元考虑,即大小为分配单元数而非实际字节数
    int yesorno; //是否空闲,1 空闲,有效
} Empty[M];

struct not_empty//已分配分区表
{
    int process_id;//作业标志符,此处采用0-255的整数
    int address_of_start;//起始地址
    int size_of_notempty;//作业请求的内存单元数
    int yesorno; //是否已分配,1 已分配 有效
} Not_Empty[N];

int CountOfEmpty = 1, CountOfNotEmpty = 0; //假定从0时刻开始,最初内存中没有作业
int Max_Size = 256;   //最大空间256 X 1kb = 256kb
int Num_Of_Row = 20; //显示时,横排个数
int Num_of_Holes = 0; //碎片空闲区个数
int Time[N];     //进程分配搜索空闲区次数
int num = 0;

bool cmp(const my_empty& a, const my_empty& b) {
    return a.address_of_start < b.address_of_start;
}

bool cmp2(const my_empty& a, const my_empty& b) {
    return a.address_of_start > b.address_of_start;
}

bool cmp_NotEmpty(const not_empty& a, const not_empty& b) {
    return a.address_of_start < b.address_of_start;
}
bool cmp_NotEmpty2(const not_empty& a, const not_empty& b) {
    return a.address_of_start > b.address_of_start;
}
int enough(int Size_Of_NotEmpty) //判断是否存在可分配给新作业的空闲区
{
    int i;
    for (i = 0; i < CountOfEmpty; i++) //首次适配 first fit
    {
        if (Empty[i].size_of_empty >= Size_Of_NotEmpty) {
            Time[num] += 1;
            num++;
            return i;
        }
        else {
            Time[num] += 1;
        }
    }
    return -1;
}

int fenpei()
{
    int temp, i;
    CountOfNotEmpty += 1;
    Not_Empty[CountOfNotEmpty].yesorno = 0;
    for (i = 0; i < CountOfNotEmpty; i++) {
        if (Not_Empty[i].yesorno == 0) {
            cout << "输入进程ID (0 ~ 255),占用空间大小(0 ~ " << 10 << ")\n";
            cin >> Not_Empty[i].process_id >> Not_Empty[i].size_of_notempty;
            if (Not_Empty[i].process_id < 0 || Not_Empty[i].process_id >255)
            {
                CountOfNotEmpty -= 1;
                cout << "进程号 0 ~ 255\n";
                return -1;
            }
            for (int ii = 0; ii < CountOfNotEmpty; ii++)
            {
                if (Not_Empty[i].process_id == Not_Empty[ii].process_id && i != ii)
                {
                    CountOfNotEmpty -= 1;
                    cout << "进程号必须唯一\n";
                    return -1;
                }
            }
            temp = enough(Not_Empty[i].size_of_notempty);
            if (temp >= 0) //找到了能满足请求的空闲分区
            {
                Not_Empty[i].address_of_start = Empty[temp].address_of_start;
                Not_Empty[i].yesorno = 1;// 占用队列有效
                Empty[temp].address_of_start += Not_Empty[i].size_of_notempty;//修改空闲队列
                Empty[temp].size_of_empty -= Not_Empty[i].size_of_notempty;
                if (Empty[temp].size_of_empty == 0) {
                    Empty[temp].yesorno = 0;
                }
                if (Empty[temp].size_of_empty <= 2 && Empty[temp].size_of_empty >= 1)
                    Num_of_Holes++;
                return 0;
            }
            else
            {
                CountOfNotEmpty -= 1;
                cout << "未找到足够大的空闲分区\n";
                return -1;
            }
        }
    }
}

int huishou() {
    int id, flag = 0;
    cout << "输入进程ID (0 ~ 255):\n";
    cin >> id;
    if (id > 255 || id < 0) {
        cout << "进程号 0 ~ 255\n";
        return -1;
    }

    for (int i = 0; i < CountOfNotEmpty; i++) { //检测回收进程是否在占用队列中
        if (Not_Empty[i].process_id == id) {
           
            int tmp_start = Not_Empty[i].address_of_start;
            int tmp_size = Not_Empty[i].size_of_notempty;
            int tmp_end = tmp_start + tmp_size;

            Not_Empty[i].process_id = 0;//回收占用进程
            Not_Empty[i].address_of_start = 0;           
            Not_Empty[i].size_of_notempty = 0;
            Not_Empty[i].yesorno = 0;
           

            //修改空闲队列
            for (int j = 0; j < CountOfEmpty; j++) {
                if (Empty[j].yesorno == 1) {
                    if (tmp_end == Empty[j].address_of_start) {//回收进程在空闲区前面,向前合并
                        Empty[j].address_of_start -= tmp_size;
                        Empty[j].size_of_empty += tmp_size;
                        flag = 1;
                        break;
                    }
                    else if (Empty[j].address_of_start + Empty[j].size_of_empty == tmp_start) {//回收进行在空闲向后合并
                        Empty[j].size_of_empty += tmp_size;
                        if (j + 1 < CountOfEmpty && Empty[j + 1].address_of_start == tmp_end) {//左右合并,空闲区个数减一                      
                            Empty[j].size_of_empty += Empty[j + 1].size_of_empty;
                            Empty[j + 1].address_of_start = 0;//清空合并空闲队列
                            Empty[j + 1].size_of_empty = 0;
                            Empty[j + 1].yesorno = 0;
                            sort(Empty, Empty + CountOfEmpty, cmp2);
                            CountOfEmpty--;
                            sort(Empty, Empty + CountOfEmpty, cmp);
                            flag = 1;
                            break;
                        }                       
                    }
                }               
            }

            if (flag == 0) {//未与已存在空闲区合并,生成独立空闲区
                Empty[CountOfEmpty].address_of_start = tmp_start;//创建空进程
                Empty[CountOfEmpty].size_of_empty = tmp_size;
                Empty[CountOfEmpty].yesorno = 1;      
                CountOfEmpty += 1;
                sort(Empty, Empty + CountOfEmpty, cmp);              
                flag = 1;
                break;
            } 
        }
    }

    if (flag == 0) {
        cout << "进程不存在" << endl;
    }

    return 1;
}

int fragment_count() {//碎片空闲分区数
    return Num_of_Holes;
}

double NumofReaserch(){
    int sum = 0;
    for (int i = 0; i < num; i++) {
        sum += Time[i];
    }
    return sum * 1.0 / num;
}

void show_empty()//显示空闲区队列【包括起始地址和空闲区大小】
{
    int i;
    cout << "\n空闲分区列表\n";
    for (i = 0; i < CountOfEmpty; i++)
    {
        if (Empty[i].yesorno == 1)
        {
            cout << Empty[i].address_of_start << ' ' << Empty[i].size_of_empty << endl;
        }
    }
    cout << "\n碎片空闲分区数: " << fragment_count() << endl;
}


void show() {
    int k = 0;
    sort(Not_Empty, Not_Empty + CountOfNotEmpty, cmp_NotEmpty);
    for (int i = 0; i < Max_Size; i++) {
        if (i % Num_Of_Row == 0) {
            cout << endl;
        }
        while (Not_Empty[k].yesorno == 0) { k++; }

        if (Not_Empty[k].address_of_start == i) {                
                for (int j = 0; j < Not_Empty[k].size_of_notempty; j++) {
                    if (j == 0) {
                        cout << Not_Empty[k].process_id;
                    }
                    else {
                        cout << "+";
                        if ((i+j+1) % Num_Of_Row == 0 && j != Not_Empty[k].size_of_notempty-1) {
                            cout << endl;
                        }
                    }
                }
                i += Not_Empty[k].size_of_notempty - 1;       
                k++;
        }
      
        else {
            cout << "-";
        }      
    }
}

int main()
{
    Empty[0].address_of_start = 0;
    Empty[0].size_of_empty = Max_Size;
    Empty[0].yesorno = 1;
    int i;
    cout << "******************Memory Size: " << Max_Size << "KB*******************\n" << endl;
    cout << "1 分配;                      2 回收;\n3 内存占用情况图;            4 退出\n";
    cout << "\n请输入你的选择(1~4):\n";
    while (cin >> i)
    {
        switch (i)
        {
        case 1:
            if (fenpei() == 0)
                show();//内存占用情况图:注意用不同符号表示某个单元是空闲还是已经分配给作业
            show_empty();//显示空闲区链
            cout<<"\n平均搜索空闲区次数: "<< NumofReaserch() <<endl;
            break;
        case 2:huishou();//回收内存【注意图1的组合情况】
            show();//内存占用情况图
            show_empty();//空闲区链
            break;
        case 3:
            show();
            break;
        case 4:return 0;
        default: break;
        }
        cout << "******************Memory Size: " << Max_Size << "KB*******************\n" << endl;
        cout << "1 分配;                      2 回收;\n3 内存占用情况图;          4 退出\n";
        cout << "\n请输入你的选择(1~4):\n";
    }
    return 0;
}

Next Fit分配法

在这里插入图片描述

// #include <iomanip>
#include <iostream>
#include<algorithm>
#define M 20
#define N 20
using namespace std;

//假定最大空闲分区20个,内存中同时最多可容纳的作业数20个
struct my_empty//空闲分区表
{
    int address_of_start; //起始地址
    int size_of_empty; //空闲大小,依据分配单元考虑,即大小为分配单元数而非实际字节数
    int yesorno; //是否空闲,1 空闲,有效
} Empty[M];

struct not_empty//已分配分区表
{
    int process_id;//作业标志符,此处采用0-255的整数
    int address_of_start;//起始地址
    int size_of_notempty;//作业请求的内存单元数
    int yesorno; //是否已分配,1 已分配 有效
} Not_Empty[N];

int CountOfEmpty = 1, CountOfNotEmpty = 0; //假定从0时刻开始,最初内存中没有作业
int Max_Size = 256;   //最大空间256 X 1kb = 256kb
int Num_Of_Row = 20; //显示时,横排个数
int Num_of_Holes = 0; //碎片空闲区个数
int Time[N];     //进程分配搜索空闲区次数
int num = 0;
int Next_fit_count = 0;
bool cmp(const my_empty& a, const my_empty& b) {
    return a.address_of_start < b.address_of_start;
}

bool cmp2(const my_empty& a, const my_empty& b) {
    return a.address_of_start > b.address_of_start;
}

bool cmp_NotEmpty(const not_empty& a, const not_empty& b) {
    return a.address_of_start < b.address_of_start;
}
bool cmp_NotEmpty2(const not_empty& a, const not_empty& b) {
    return a.address_of_start > b.address_of_start;
}
int enough(int Size_Of_NotEmpty) //判断是否存在可分配给新作业的空闲区
{
    for (int i = Next_fit_count; i < CountOfEmpty; i++) //nest fit
    {
        if (Empty[i].size_of_empty >= Size_Of_NotEmpty) {
            Time[num] += 1;
            num++;
            Next_fit_count = i;
            return i;
        }
        else {
            Time[num] += 1;
        }
    }

    for (int i = 0; i < Next_fit_count; i++) //nest fit
    {
        if (Empty[i].size_of_empty >= Size_Of_NotEmpty) {
            Time[num] += 1;
            num++;
            return i;
        }
        else {
            Time[num] += 1;
        }
    }

    return -1;
}

int fenpei()
{
    int temp, i;
    CountOfNotEmpty += 1;
    Not_Empty[CountOfNotEmpty].yesorno = 0;
    for (i = 0; i < CountOfNotEmpty; i++) {
        if (Not_Empty[i].yesorno == 0) {
            cout << "输入进程ID (0 ~ 255),占用空间大小(0 ~ " << 10 << ")\n";
            cin >> Not_Empty[i].process_id >> Not_Empty[i].size_of_notempty;
            if (Not_Empty[i].process_id < 0 || Not_Empty[i].process_id >255)
            {
                CountOfNotEmpty -= 1;
                cout << "进程号 0 ~ 255\n";
                return -1;
            }
            for (int ii = 0; ii < CountOfNotEmpty; ii++)
            {
                if (Not_Empty[i].process_id == Not_Empty[ii].process_id && i != ii)
                {
                    CountOfNotEmpty -= 1;
                    cout << "进程号必须唯一\n";
                    return -1;
                }
            }
            temp = enough(Not_Empty[i].size_of_notempty);
            if (temp >= 0) //找到了能满足请求的空闲分区
            {
                Not_Empty[i].address_of_start = Empty[temp].address_of_start;
                Not_Empty[i].yesorno = 1;// 占用队列有效
                Empty[temp].address_of_start += Not_Empty[i].size_of_notempty;//修改空闲队列
                Empty[temp].size_of_empty -= Not_Empty[i].size_of_notempty;
                if (Empty[temp].size_of_empty == 0) {
                    Empty[temp].yesorno = 0;
                }
                if (Empty[temp].size_of_empty <= 2 && Empty[temp].size_of_empty >= 1)
                    Num_of_Holes++;
                return 0;
            }
            else
            {
                CountOfNotEmpty -= 1;
                cout << "未找到足够大的空闲分区\n";
                return -1;
            }
        }
    }
}

int huishou() {
    int id, flag = 0;
    cout << "输入进程ID (0 ~ 255):\n";
    cin >> id;
    if (id > 255 || id < 0) {
        cout << "进程号 0 ~ 255\n";
        return -1;
    }

    for (int i = 0; i < CountOfNotEmpty; i++) { //检测回收进程是否在占用队列中
        if (Not_Empty[i].process_id == id) {
           
            int tmp_start = Not_Empty[i].address_of_start;
            int tmp_size = Not_Empty[i].size_of_notempty;
            int tmp_end = tmp_start + tmp_size;

            Not_Empty[i].process_id = 0;//回收占用进程
            Not_Empty[i].address_of_start = 0;           
            Not_Empty[i].size_of_notempty = 0;
            Not_Empty[i].yesorno = 0;
           

            //修改空闲队列
            for (int j = 0; j < CountOfEmpty; j++) {
                if (Empty[j].yesorno == 1) {
                    if (tmp_end == Empty[j].address_of_start) {//回收进程在空闲区前面,向前合并
                        Empty[j].address_of_start -= tmp_size;
                        Empty[j].size_of_empty += tmp_size;
                        flag = 1;
                        break;
                    }
                    else if (Empty[j].address_of_start + Empty[j].size_of_empty == tmp_start) {//回收进行在空闲向后合并
                        Empty[j].size_of_empty += tmp_size;
                        if (j + 1 < CountOfEmpty && Empty[j + 1].address_of_start == tmp_end) {//左右合并,空闲区个数减一                      
                            Empty[j].size_of_empty += Empty[j + 1].size_of_empty;
                            Empty[j + 1].address_of_start = 0;//清空合并空闲队列
                            Empty[j + 1].size_of_empty = 0;
                            Empty[j + 1].yesorno = 0;
                            sort(Empty, Empty + CountOfEmpty, cmp2);
                            CountOfEmpty--;
                            sort(Empty, Empty + CountOfEmpty, cmp);
                            flag = 1;
                            break;
                        }                       
                    }
                }               
            }

            if (flag == 0) {//未与已存在空闲区合并,生成独立空闲区
                Empty[CountOfEmpty].address_of_start = tmp_start;//创建空进程
                Empty[CountOfEmpty].size_of_empty = tmp_size;
                Empty[CountOfEmpty].yesorno = 1;      
                CountOfEmpty += 1;
                sort(Empty, Empty + CountOfEmpty, cmp);              
                flag = 1;
                break;
            } 
        }
    }

    if (flag == 0) {
        cout << "进程不存在" << endl;
    }

    return 1;
}

int fragment_count() {//碎片空闲分区数
    return Num_of_Holes;
}

double NumofReaserch(){
    int sum = 0;
    for (int i = 0; i < num; i++) {
        sum += Time[i];
    }
    return sum * 1.0 / num;
}

void show_empty()//显示空闲区队列【包括起始地址和空闲区大小】
{
    int i;
    cout << "\n空闲分区列表\n";
    for (i = 0; i < CountOfEmpty; i++)
    {
        if (Empty[i].yesorno == 1)
        {
            cout << Empty[i].address_of_start << ' ' << Empty[i].size_of_empty << endl;
        }
    }
    cout << "\n碎片空闲分区数: " << fragment_count() << endl;
}


void show() {
    int k = 0;
    sort(Not_Empty, Not_Empty + CountOfNotEmpty, cmp_NotEmpty);
    for (int i = 0; i < Max_Size; i++) {
        if (i % Num_Of_Row == 0) {
            cout << endl;
        }
        while (Not_Empty[k].yesorno == 0) { k++; }

        if (Not_Empty[k].address_of_start == i) {                
                for (int j = 0; j < Not_Empty[k].size_of_notempty; j++) {
                    if (j == 0) {
                        cout << Not_Empty[k].process_id;
                    }
                    else {
                        cout << "+";
                        if ((i+j+1) % Num_Of_Row == 0 && j != Not_Empty[k].size_of_notempty-1) {
                            cout << endl;
                        }
                    }
                }
                i += Not_Empty[k].size_of_notempty - 1;       
                k++;
        }
      
        else {
            cout << "-";
        }      
    }
}

int main()
{
    Empty[0].address_of_start = 0;
    Empty[0].size_of_empty = Max_Size;
    Empty[0].yesorno = 1;
    int i;
    cout << "******************Memory Size: " << Max_Size << "KB*******************\n" << endl;
    cout << "1 分配;                      2 回收;\n3 内存占用情况图;            4 退出\n";
    cout << "\n请输入你的选择(1~4):\n";
    while (cin >> i)
    {
        switch (i)
        {
        case 1:
            if (fenpei() == 0)
                show();//内存占用情况图:注意用不同符号表示某个单元是空闲还是已经分配给作业
            show_empty();//显示空闲区链
            cout<<"\n平均搜索空闲区次数: "<< NumofReaserch() <<endl;
            break;
        case 2:huishou();//回收内存【注意图1的组合情况】
            show();//内存占用情况图
            show_empty();//空闲区链
            break;
        case 3:
            show();
            break;
        case 4:return 0;
        default: break;
        }
        cout << "******************Memory Size: " << Max_Size << "KB*******************\n" << endl;
        cout << "1 分配;                      2 回收;\n3 内存占用情况图;          4 退出\n";
        cout << "\n请输入你的选择(1~4):\n";
    }
    return 0;
}
  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值