操作系统内存管理(分区分配)

1、实验内容

分区分配算法至少实现首次适应算法、最佳适应算法和最坏适应算法中的;至少两种。

熟悉并掌握各种算法的空闲区组织方式。

分区的初始化——可以由用户输入初始分区的大小。(初始化后只有一个空闲分区,起

始地址为 0,大小是用户输入的大小)

分区的动态分配过程:由用户输入作业号和作业的大小,实现分区过程。

分区的回收:用户输入作业号,实现分区回收,同时,分区的合并要体现出来。(注意:

不存在的作业号要给出错误提示!)

分区的显示:任何时刻,可以查看当前内存的情况(起始地址是什么,大小多大的分

区是空闲的,或者占用的,能够显示出来)。

2、实验要求

1)内存空间不足的情况,要有相应的显示;

2)作业不能同名,但是删除后可以再用这个名字;

3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有

相应的提示;

4)实现 FFBFWF 内存分配算法中的至少两种;

#include<stdio.h>
#include<stdlib.h>

typedef struct lei_item       //表示空闲分区表中的表箱
{
    int id;                 //假如 id 为-1,表示此分区时一个空闲分区。
    int base;              //指向分区的首地址
    int size;               //表示分区大小
    int status;             //表示此分区是否已经分配     0表示空闲  1表示已经分配
}Item;
typedef Item datatype;

typedef struct lei_list
{
    datatype* node;      //表示一个datatype类型的链表的结点
    struct lei_list* front;
    struct lei_list* next;
}List;

#define Max 640
int memory = Max;       //定义可用内存空间为640



List init(){            //初始化一个链表;
    List list;
    list.node = (datatype *)malloc(sizeof(datatype));
    list.node->base = 0;
    list.node->id = -1;                     //-1表示是空闲分区
    list.node->size = memory;
    list.node->status = 0;
    list.front = list.next = NULL;
    return list;
}

datatype* input(){          //初始化打算申请的内存分区节点
    datatype* item = (datatype *)malloc(sizeof(datatype));
    printf("请输入作业号:");
    scanf("%d",&item->id);
    printf("请输入所需要的内存的大小:");
    scanf("%d",&item->size);
    item->status = 0;
    return item;
}
void Momery_state(List *list){
    List* temp = list;
    printf("-----------------------------------\n");
    printf("内存分配状况\n");
    printf("-----------------------------------\n");
    while (temp)
    {
        if(temp->node->status == 0 && temp->node->id == -1){
            printf("分区号:FREE\n");
            printf("起始地址:%d\n",temp->node->base);
            printf("内存大小:%d\n",temp->node->size);
            printf("分区状态:空闲\n");
        }
        else
        {
            printf("分区号:%d\t起始地址:%d\n",temp->node->id,temp->node->base);
            printf("内存大小:%d\n",temp->node->size);
            printf("分区状态:已分配\n");
        }
        printf("-----------------------------------\n");
        temp = temp->next;
    }

}

int First_fit(List *list){
    datatype* item = input();
    List* temp = list;                      //定义一个临时变量list* ,指向list

    while (temp)
    {

        if(temp->node->status == 0 && temp->node->size > item->size){       //如果此前的分区未分配,,并且分区大小大于 请求分配的大小     那么此时就可以进行分配
            List *front = temp->front;                                          //存储当前未分配分区的 上一个分区地址
            List *next = temp->next;                                          //存储当前未分配分区的  下一个分区地址
            int base = temp->node->base;                                      //记录未分配当前分区的首地址

            datatype* new_node = (datatype*)malloc(sizeof(datatype));          // 多余出来的部分要新建立一个分区
            new_node->id = -1;                                                 //然后需要对这个新的分区进行一些信息的设置
            new_node->size = temp->node->size - item->size;         //新分区的大小  等于  还未分配的时的分区大小 - 请求分配的结点的大小

            temp->node = item;                                  //对请求分配的分区结点进行分配
            temp->node->status = 1;

            new_node->status = 0;
            new_node->base = base + temp->node->size;             //新建立分区的首地址是  请求分配的分区的首地址 + 请求分配的分区的大小


            List* temp_next = (List*)malloc(sizeof(List));           //临时节点 (申请一个新的链表节点 表示下一个分区)  并且进行初始化
            temp_next->node = new_node;                             //保存下一个的分区的信息
            temp_next->front = temp_next->next = NULL;

            if(front == NULL && next == NULL){                      //如果 front和next节点都是空,表明它是第一次分配分区
                temp->node->base = 0;                               //初始化首地址
                temp->next = temp_next;
                temp_next->front = temp;
            }
            if(front == NULL && next != NULL){                 //在第一个分区中插入新的分区
                temp->node->base = 0;
                temp->node->status = 1;
                temp_next->front = temp;
                temp_next->next = temp->next;
                temp->next = temp_next;
            }
            if(front != NULL){                      //表明不是第一次分配节点,此时需要在中间插入下一个节点
                temp->node->base = temp->front->node->base+temp->front->node->size;        //初始化首地址
                temp_next->next = temp->next;                                       //保证新插入的节点会记录原先节点的下一个节点的首地址
                temp_next->front = temp;                               // 首尾都需要保证
                temp->next = temp_next;                             //最后让所申请的分区节点的下一个节点指向  我们刚刚建立的临时节点
            }
            return 1;
        }
        else if(temp->node->status == 0 && temp->node->size == item->size)
        {
            item->base = temp->front->node->base+temp->front->node->size;               //新插入分区的首地址  等于上一个分区的 首地址+分区的大小
            item->status = 1;                                           //表示已经分配
            temp->node = item;

            return 1;
        }
        else{
            temp = temp->next;
            continue;
        }
        temp = temp->next;
    }
    return 0;
}

int Momory_recycle(List *list){
    List* temp = list;                      //申请一个链表节点 指向list 的头节点
    int number;                         //用于存放要释放的节点的分区号
    printf("请输入需要回收的ID号:");
    scanf("%d",&number);
    while (temp)
    {
        if(temp->node->id == number)            //首先找到 节点id = number 的节点,然后分四种情况讨论
        {
            // 一、 要回收的是第一个结点
            if(temp->front == NULL){
                temp->node->status = 0;
                temp->node->id = -1;
                if(temp->next == NULL){
                    temp->node->size = temp->node->size + temp->next->node->size;
                    temp->next = temp->next;
                    return 1;
                }

                if(temp->next->node->id == -1 && temp->next->node->status == 0){
                    List* next = temp->next;
                    // 此时来判断 temp->next 是否是系统的最后一个结点
                    // 此时只将当前节点 和下一个结点合并就可以了
                    //即 首地址不变,   分区状态 和 分区id进行变化
                    temp->node->size = temp->node->size + next->node->size;
                    temp->node->status = 0;
                    temp->node->id = -1;
                    temp->next = next->next;
                    if(next->next == NULL){
                        free(next);
                        return 1;
                    }
                        //如果不是最后一个结点的话就会多一个步骤
                        // 让 next->next->front 指向上一个结点
                    else
                    {
                        next->next->front = temp;
                        free(next);
                        return 1;
                    }
                }

                return 1;
            }
            //二、 前后都没有空闲的分区
            //最简单,   直接改变 分区的 id 和 分区的状态就可以了。
            // 如果回收第一个分区的话 必须要先进行处理,如果不先进行处理 ,判断 temp->front->node->id != -1 会报一个段错误。因为temp-》front 此时指向的是null
            if(temp->front->node->id != -1 && temp->front->node->status != 0 && temp->next->node->id != -1 && temp->next->node->status != 0){
                temp->node->status = 0;
                temp->node->id = -1;
                return 1;
            }
            //三、要回收的节点    前面和后面都是空闲的
            // 将三个空闲区合并到一起,起始地址为前面的分区的起始地址, 大小为三个空闲区大小之和
            //还需要做一个判断,如果
            if(temp->front->node->id == -1 && temp->front->node->status == 0 && temp->next->node->id == -1 && temp->next->node->status == 0){
                List* front = temp->front;
                List* next = temp->next;
                front->node->size = front->node->size + temp->node->size + next->node->size;
                front->next = next->next;
                if(next->next == NULL){
                    free(temp);
                    return 1;
                }
                    //如果不是最后一个结点的话就会多一个步骤
                    // 让 next->next->front 指向上一个结点
                else
                {

                    next->next->front = front;
                    free(temp);
                    return 1;
                }
                return 1;
            }
            // 四、 要回收的节点  前面的节点是空闲的
            //合并后的分区起始地址为前一个结点, 分区大小为前一个节点 与 当前节点之和。
            if(temp->front->node->id == -1 && temp->front->node->status == 0){
                List* front = temp->front;
                front->next = temp->next;
                temp->next->front = front;
                front->node->size += temp->node->size;
                free(temp);
                return 1;
            }
            //五、 要回收的节点    后面的额节点是空闲的
            //合并后的分区首地址为当前节点 ,  分区大小为当前节点 与 当前节点的下一个结点大小之和。
            // 这个需要多一个步骤, 改变分区的 id 和  分区的状态。
            // 还要注意一点:  当要回收的空间是和  系统最后的空闲区相邻时 , temp->next->next 指向的是null;

            if(temp->next->node->id == -1 && temp->next->node->status == 0){
                List* next = temp->next;
                // 此时来判断 temp->next 是否是系统的最后一个结点
                // 此时只将当前节点 和下一个结点合并就可以了
                //即 首地址不变,   分区状态 和 分区id进行变化
                temp->node->size = temp->node->size + next->node->size;
                temp->node->status = 0;
                temp->node->id = -1;
                temp->next = next->next;
                if(next->next == NULL){
                    free(next);
                    return 1;
                }
                    //如果不是最后一个结点的话就会多一个步骤
                    // 让 next->next->front 指向上一个结点
                else
                {
                    next->next->front = temp;
                    free(next);
                    return 1;
                }
            }
        }
        temp = temp->next;
    }
    return 0;
}


int Best_fit(List *list){
    int min = 0;        //记录 最小分区的结点的大小
    int base_min = 0;      //记录 最小节点的结点的起始地址
    List* temp = list;
    datatype* item = input();              // 要对 item 的 起始地址  和 分配状态进行初始化

    while (temp)
    {
        //如果分区未分配   就要进行  比较操作, 并且记录差值 和 分区的id号
        if(temp->node->status == 0 && temp->node->id == -1&& temp->node->size > item->size){
            if(min == 0){          //加入min为0 表示还未找到一个可以分配的分区
                min = temp->node->size;
                base_min = temp->node->base;
            }
            else
            {
                if(temp->node->size < min){      // 找到一个之后,需要找出最小的分区  也就是它的  size最小。
                    min = temp->node->size;
                    base_min = temp->node->base;
                }
            }

        }
        if(temp->node->status == 0 && temp->node->id == -1 && temp->node->size == item->size){
            int base = temp->node->base;
            temp->node = item;
            temp->node->status = 1;
            temp->node->base = base;
            return 1;
        }
        temp = temp->next;
    }

    //因为可能没有任何一个空间可以满足要求需要做一个判断处理
    temp = list;
    while (temp)
    {
        if(temp->node->base == base_min){

            datatype* temp_node = (datatype*)malloc(sizeof(datatype));      //会有多余的空间多出来  所以需要在建立一个结点插入到链表中
            temp_node->id = -1;
            temp_node->status = 0;
            temp_node->base = base_min + item->size;
            temp_node->size = temp->node->size - item->size;

            temp->node = item;                          //对item进行完整的初始化
            temp->node->base = base_min;
            temp->node->status = 1;

            List* temp_list_node = (List*)malloc(sizeof(List));         //新申请一个 链表的结点 并且初始化
            temp_list_node->node = temp_node;
            temp_list_node->front = temp;
            temp_list_node->next = temp->next;
            if(temp->next != NULL){
                temp->next->front = temp_list_node;
            }
            temp->next = temp_list_node;
            return 1;
        }
        temp = temp->next;
    }

}


int main(){
    printf("分区模拟\n");
    List list = init();
    int select;
    int insert_state,recycle_state;
    int insert_state_best;
    do
    {
        printf("请输入要进行的操作\n");
        printf("1-首次适应算法, 2-最佳适应算法, 3-内存回收, 4-显示内存状况, 5-退出\n");
        scanf("%d",&select);
        switch (select)
        {
            case 1:              // 1. 首次适应算法
                insert_state = First_fit(&list);
                if(insert_state == 0){
                    printf("分配失败\n");
                }
                else {
                    printf("分配成功!\n");
                }
                break;
            case 2:             // 2. 最佳适应算法
                insert_state_best = Best_fit(&list);
                if(insert_state_best == 1){
                    printf("分配成功\n");
                }
                else  {
                    printf("分配失败\n");
                }
                break;
            case 3:             //3.内存回收
                recycle_state = Momory_recycle(&list);
                if(recycle_state == 1){
                    printf("回收成功!\n");
                }
                else{
                    printf("回收失败\n");
                }
                break;
            case 4:             //4.显示内存状况
                Momery_state(&list);
                break;
        }
    } while (select != 5);

    system("pause");
}

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值