操作系统–动态分区存储管理

实验内容:

分区分配算法至少实现首次适应算法、最佳适应算法和最坏适应算法中的至少一种。熟悉并掌握各种算法的空闲区组织方式。
分区的初始化——可以由用户输入初始分区的大小。(初始化后只有一个空闲分区,起始地址为0,大小是用户输入的大小)
分区的动态分配过程:由用户输入作业号和作业的大小,实现分区过程。
分区的回收:用户输入作业号,实现分区回收,同时,分区的合并要体现出来。(注意:不存在的作业号要给出错误提示!)
分区的显示:任何时刻,可以查看当前内存的情况(起始地址是什么,大小多大的分区时空闲的,或者占用的,能够显示出来)。

代码:

#include <iostream>
#include <string>
#include <cstdio>
#include <map>
#include <cstdlib>

using namespace std;
const int MAX = 109;
const int INF = 1 << 30;

struct WORK
{
    int work_id; // 作业号
    int work_size; // 作业大小
    bool is_load; //作业是否被装入分区
    bool is_delete; // 作业是否回收
    WORK & operator=(const WORK &w)
    {
        work_id = w.work_id;
        work_size = w.work_size;
        is_load = w.is_load;
        is_delete = w.is_delete;
        return *this;
    }
};

struct SUBAREA
{
    int area_size; // 分区大小
    int area_id; // 分区编号
    bool exist_work; // 该分区是否有作业
    WORK current_work; // 当前存放的作业
    SUBAREA & operator=(const SUBAREA &s)  // 重载赋值运算符
    {
        area_size = s.area_size;
        area_id = s.area_id;
        exist_work = s.exist_work;
        current_work = s.current_work;
        return *this;
    }
};

SUBAREA subarea[MAX];
WORK work[MAX];
int subarea_size; // 初始分区的大小
int work_num; // 作业数量
int subarea_num; // 分区数量
map<int, bool> exist_work;
map<int, int> work_pos;

void init() // 初始化
{
    for(int i = 0; i < MAX; i++)
    {
        work[i].is_load = work[i].is_delete = false;
        subarea[i].exist_work = false;
        subarea[i].current_work.work_id = -1;
    }
}

int order_insert_subarea(WORK w, int s_num) // 最初将作业顺序装入分区,传入作业和分区数量
{
    int insert_num = -1; // 该作业装入的分区编号
    int sum = 0;
    int next_s = 0;
    for(int i = 0; i < s_num; i++)
    {
        //printf("sum = %d workSize = %d subsize = %d\n", sum, w.work_size, subarea[i].area_size);
        if(subarea[i].exist_work)
        {
            sum += subarea[i].current_work.work_size;
        }
        else if(w.work_size <= subarea[i].area_size && !subarea[i].exist_work) // 作业大小小于等于当前分区大小并且该分区空闲则可以装入
        {
            sum += w.work_size;
            subarea[i].current_work = w;
            subarea[i].area_size = w.work_size;
            subarea[i].exist_work = true;
            subarea[i].area_id = i;
            insert_num = i;
            next_s = i + 1;
            break;
        }
    }

    if(insert_num != -1) // 装入作业成功,进行分区
    {
        subarea_num ++; // 分区数量加一
        // 更新分区信息
        subarea[next_s].area_id = next_s;
        subarea[next_s].area_size = subarea_size - sum;
        subarea[next_s].exist_work = false;
        subarea[next_s].current_work.work_id = -1;
    }
//    printf("insert_num = %d\n", insert_num);
//    printf("suba_num = %d\n", subarea_num);
    return insert_num;
}

int judge_worknum(int nu) // 判断作业号是否存在
{
    int exist_pos = -1;
    for(int i = 0; i < subarea_num; i++)
    {
        if(subarea[i].current_work.work_id == nu)
        {
            exist_pos = i;
            return exist_pos;
        }
    }
    return exist_pos;
}

void recycle_work(int p) // 回收作业
{
    int s_num = 0;
    bool before = false;
    bool next = false;
    for(int i = 0; i < subarea_num - 1; i++)
    {
        if(i == p)
        {
            if( i != 0 && !subarea[i - 1].exist_work) // 前一个分区空闲
            {
                // 与待回收的作业合并
                before = true;
                s_num++;
            }
            if(!subarea[i + 1].exist_work) // 后一个分区空闲
            {
                // 与待回收的作业合并
                next = true;
                s_num++;
            }
            break;
        }
    }

    if(before || next) // 待回收的作业前后有空弦分区
    {
        if(before && !next) // 前有空闲后没有
        {
            //cout << p << "前空闲后不空闲" << endl;
            subarea[p - 1].exist_work = false; // 合并后该分区不存在作业
            subarea[p - 1].current_work.work_id = -1;
            subarea[p - 1].area_size += subarea[p].area_size;
            for(int i = p; i < subarea_num - 1; i++)
            {
                subarea[i] = subarea[i + 1];
                subarea[i].area_id = i;
            }

            subarea_num --;
        }
        else if(!before && next) // 后有空闲前没有
        {
            //cout  << p << "前不空闲后空闲" << endl;
            subarea[p].exist_work = false;
            subarea[p].current_work.work_id = -1;
            subarea[p].area_size += subarea[p + 1].area_size;
            for(int i = p + 1; i < subarea_num - 1; i++)
            {
                subarea[i] = subarea[i + 1];
                subarea[i].area_id = i;
            }
            subarea_num --;
        }
        else // 前后都有空闲
        {
            //cout  << p << "前后都空闲" << endl;
            subarea[p - 1].exist_work = false;
            subarea[p - 1].current_work.work_id = -1;
            subarea[p - 1].area_size += (subarea[p].area_size + subarea[p + 1].area_size);
            for(int i = p; i < subarea_num - 2; i++)
            {
                subarea[i] = subarea[i + 2];
                subarea[i].area_id = i;
            }
            subarea_num -= 2;
        }
    }
    else // 前后都没有空闲
    {
        subarea[p].exist_work = false;
        subarea[p].current_work.work_id = -1;
    }
}



int first_fit(WORK cur) // 首次适应算法
{
    for(int i = 0; i < subarea_num; i++)
    {
        // 当前分区不存在作业且分区大小够装入作业
        if(!subarea[i].exist_work && subarea[i].area_size >= cur.work_size)
        {
            return i;
        }
    }
    return -1;
}

int best_fit(WORK cur) // 最佳适应算法
{
    int minn = INF;
    int minn_id = -1;
    for(int i = 0; i < subarea_num; i++)
    {
        // 当前分区不存在作业且分区大小够装入作业
        // 更新最小能装下的分区编号
        if(!subarea[i].exist_work &&  subarea[i].area_size >= cur.work_size && subarea[i].area_size < minn)
        {
            minn = subarea[i].area_size;
            minn_id = i;
        }
    }
    return minn_id;
}

int worst_fit(WORK cur) // 最坏适应算法
{
    int maxx = -1;
    int max_id = -1;
    for(int i = 0; i < subarea_num; i++)
    {
        // 当前分区不存在作业且分区大小够装入作业
        // 更新最小能装下的分区编号
        if(!subarea[i].exist_work &&  subarea[i].area_size >= cur.work_size && subarea[i].area_size > maxx)
        {
            maxx = subarea[i].area_size;
            max_id = i;
        }
    }
    return max_id;
}

void update_subarea(int posi, WORK cur) // 更新分区
{
    int t = subarea[posi].area_size - cur.work_size;
    if(t == 0) // 刚好装满分区
    {
        subarea[posi].current_work = cur;
        subarea[posi].exist_work = true;
        return;
    }

    subarea[posi].area_size = cur.work_size;
    subarea[posi].area_id = posi;
    subarea[posi].current_work = cur;
    subarea[posi].exist_work = true;
    // 更新分区
    for(int j = subarea_num; j > posi + 1; j--)
    {
        subarea[j] = subarea[j - 1];
    }
    subarea[posi + 1].area_size = t;
    subarea[posi + 1].area_id = posi + 1;
    subarea[posi + 1].exist_work = false;
    subarea[posi + 1].current_work.work_id = -1;
    subarea_num++;
}



int main()
{
    while(true)
    {
        init();
        cout << "***********请选择你想实现的算法:***************" << endl;
        cout << "************* 1、首次适应算法 ******************" << endl;
        cout << "************* 2、最佳适应算法 ******************" << endl;
        cout << "************* 3、最坏适应算法 ******************" << endl;
        cout << "*****************  0、退出 *********************" << endl;

        int sel;
        cin >> sel;
        if(sel == 0)
            break;

        cout << "请输入初始分区的大小:" << endl;
        cin >> subarea_size;

        // 初始化
        subarea_num = 1;
        subarea[0].area_id = 0;
        subarea[0].area_size = subarea_size;

        cout << "请输入待处理的作业个数: ";
        cin >>  work_num;

        cout << "请输入各个作业信息(作业号 + 作业大小):" << endl;
        for(int i = 0; i < work_num; i++)
        {
            cin >> work[i].work_id >> work[i].work_size;
            exist_work[work[i].work_id] = true;
            work_pos[work[i].work_id] = i;
        }


        // 初始状态下顺序装入
        int load_work_num = 0;
        bool exist_unwork = false;
        for(int i = 0; i < work_num; i++)
        {
            int t_num = order_insert_subarea(work[i], subarea_num);
            if(t_num != -1)
            {
                load_work_num++;
                work[i].is_load = true;
                cout << "作业 " << work[i].work_id << " 成功装入分区 " << t_num << endl;
            }
            else
            {
                cout << "作业 " << work[i].work_id << "暂无可用分区,等待回收...."  << endl;
                exist_unwork = true;
                //break;
            }
        }

        cout << endl;
        if(load_work_num != work_num)
        {
            cout << "存在 " << work_num - load_work_num << "个作业未装入,等待回收...." << endl;
        }

        //printf("load_num = %d worknum = %d\n", load_work_num, work_num);

        while(load_work_num != work_num)
        {
            cout << "存在未装入的作业,请选择: 1、回收  其他、装入" << endl;
            int se;
            cin >> se;
            if(se == 1)
            {
                int rework_num;
                cout << "请输入待回收的作业号:";
                cin >> rework_num;

                int pos = judge_worknum(rework_num); // 获取待回收作业在分区中的位置

                if(pos == -1) // 要回收的作业号不存在
                    cout << "您要回收的作业号不存在!" << endl;

                else // 进行回收
                {
                    recycle_work(pos);

                    cout << "回收后的分区状况:" << endl;
                    printf("%10s%10s%10s\n", "是否空闲", "分区编号", "分区大小");
                    for(int i = 0; i < subarea_num; i++)
                        printf("%10d%10d%10d\n", subarea[i].exist_work, subarea[i].area_id, subarea[i].area_size);
                }
            }

            else // 继续装入未装入的作业 (三种算法)
            {
                int load_id;
                cout << "请输入要装入的作业编号:";
                cin >> load_id;

                int temp = judge_worknum(load_id);

                if(temp != -1) // 要装入的作业号已经装入
                    cout << "您要装入的作业已装入,请勿重复装入!" << endl;
                else if(!exist_work[load_id])
                    cout << "您要装入的作业不存在!" << endl;
                else
                {
                    int suit_pos = work_pos[load_id];
                    int area_pos;
                    if(sel == 1) // 首次适应算法
                    {
                        area_pos = first_fit(work[suit_pos]);
                        if(area_pos == -1)
                        {
                            cout << "暂无可用分区!" << endl;
                        }
                        else
                        {
                            update_subarea(area_pos, work[suit_pos]);
                            load_work_num ++;
                            cout << "已成功装入分区,装入后的分区分配如下:" << endl;
                            printf("%20s%20s%20s%20s%20s\n", "是否空闲", "分区编号", "分区大小", "装入的作业号", "装入的作业大小");
                            for(int i = 0; i < subarea_num; i++)
                                printf("%20d%20d%20d%20d%20d\n", subarea[i].exist_work, subarea[i].area_id, subarea[i].area_size, subarea[i].current_work.work_id, subarea[i].current_work.work_size);
                        }
                    }
                    else if(sel == 2) // 最佳适应算法
                    {
                        area_pos = best_fit(work[suit_pos]);
                        if(area_pos == -1)
                        {
                            cout << "暂无可用分区!" << endl;
                        }
                        else
                        {
                            update_subarea(area_pos, work[suit_pos]);
                            load_work_num ++;
                            cout << "已成功装入分区,装入后的分区分配如下:" << endl;
                            printf("%20s%20s%20s%20s%20s\n", "是否空闲", "分区编号", "分区大小", "装入的作业号", "装入的作业大小");
                            for(int i = 0; i < subarea_num; i++)
                                printf("%20d%20d%20d%20d%20d\n", subarea[i].exist_work, subarea[i].area_id, subarea[i].area_size, subarea[i].current_work.work_id, subarea[i].current_work.work_size);
                        }
                    }
                    else // 最坏适应算法
                    {
                        area_pos = worst_fit(work[suit_pos]);
                        load_work_num ++;
                        if(area_pos == -1)
                        {
                            cout << "暂无可用分区!" << endl;
                        }
                        else
                        {
                            update_subarea(area_pos, work[suit_pos]);
                           cout << "已成功装入分区,装入后的分区分配如下:" << endl;
                            printf("%20s%20s%20s%20s%20s\n", "是否空闲", "分区编号", "分区大小", "装入的作业号", "装入的作业大小");
                            for(int i = 0; i < subarea_num; i++)
                                printf("%20d%20d%20d%20d%20d\n", subarea[i].exist_work, subarea[i].area_id, subarea[i].area_size, subarea[i].current_work.work_id, subarea[i].current_work.work_size);
                        }
                    }
                }
                if(load_work_num == work_num)
                    cout << "所有作业均已全部装入!" << endl;
            }
        }
        system("pause");
        system("clear");
    }
    return 0;
}

如有错误,欢迎指正~~