操作系统|C语言模拟实现首次适应和最佳适应两种内存分配算法以及内存回收

两种算法

  • 首次适应

    首次适应算法从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。

  • 最佳适应

    最佳适应算法是指从全部空闲区中找出能满足作业要求且大小最小的空闲分区的一种计算方法,这种方法能使碎片尽量小。

程序代码

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

struct area
{
  int id;             // 编号
  int addr_front;     //首地址
  int size;           //分区大小
  int flag;           //分配标志
  struct area *front; //上一分区
  struct area *next;  //下一分区
};

typedef struct area partion;

partion *head = NULL; //分区队列头节点
int need;             //需求
int choice = 1;       //操作选项

partion *createPartion(int id, int addr_front, int size, int flag); //生成一个节点
void inputNeed();                                                   //输入需求量
void assign(partion *ptr, int need);                                //分配分区
void first_fit();                                                   //首次适应算法
void best_fit();                                                    //最佳适应算法
void showMemoryInfo();                                              //打印分区分配状况
void recovery();                                                    //分区回收
void changeIdValue(partion *ptr, int delta);                        //改变从ptr开始所有节点的id值

int main(void)
{
  head = createPartion(0, 0, 200, 0);
  while (choice != 0)
  {
    puts("-------------------\nchoose operation:\n1:First_Fit;\n2:Best_Fit;\n3:recovery;\n4:showinformation;\n0:quit......\n-------------------");
    scanf("%d", &choice);
    switch (choice)
    {
    case 1:
      inputNeed();
      first_fit();
      break;
    case 2:
      inputNeed();
      best_fit();
      break;
    case 3:
      recovery();
      break;
    case 4:
      showMemoryInfo();
      break;
    case 0:
      puts("byebye");
      break;
    default:
      break;
    }
  }

  system("pause");
  return 0;
}

partion *createPartion(int id, int addr_front, int size, int flag)
{
  partion *p = (partion *)malloc(sizeof(partion));
  p->id = id;
  p->addr_front = addr_front;
  p->size = size;
  p->flag = flag;
  p->front = NULL;
  p->next = NULL;
  return p;
}

void inputNeed()
{
  printf("please input the need:");
  scanf("%d", &need);
}

void first_fit()
{
  partion *fit = NULL;
  partion *ptr = head;
  while (ptr != NULL)
  {
    if (ptr->size >= need && ptr->flag == 0)
    {
      fit = ptr;
      break;
    }
    ptr = ptr->next;
  }
  if (fit != NULL)
  {
    assign(fit, need);
    printf("assigned successfully!\n");
  }
  else
  {
    puts("Sorry,there is no appropriate partion!");
    free(fit);
  }
}

void best_fit()
{
  partion *fit = NULL;
  partion *ptr = head;
  int flag = 0; //flag 表示是否找到可分配的分区
  while (ptr != NULL)
  {
    if (ptr->flag == 0 && ptr->size >= need)
    {
      if (flag == 0)
      {
        //只有遇到的第一个可分配分区回执行此操作
        fit = ptr;
        flag = 1;
      }
      else
      {
        //若遇到可分配且分区更小即更适合的则更新
        if (ptr->size < fit->size)
        {
          fit = ptr;
        }
      }
    }
    ptr = ptr->next;
  }
  //先处理没找到合适分区的情况
  if (flag == 0)
  {
    puts("Sorry,there is no appropriate partion!");
    free(fit);
    return;
  }
  //找到则分配
  assign(fit, need);
  puts("assigned successfully!");
}

void showMemoryInfo()
{
  partion *ptr = head;
  puts("\n\n---------------------------------------------");
  puts("Here is the information of memory:");
  puts("---------------------------------------------");
  while (ptr != NULL)
  {
    printf("id:%21d%10c\nfront address:%10d%10c\n", ptr->id, '|', ptr->addr_front, '|');
    printf("partion size:%11d%10c\n", ptr->size, '|');
    printf("status:%17s%10c\n", ptr->flag == 0 ? "available" : "busy", '|');
    puts("----------------------------------");
    ptr = ptr->next;
  }
  puts("---------------------------------------------\n\n");
}

void assign(partion *ptr, int need)
{

  if (need == ptr->size)
  {
    ptr->flag = 1;
    return;
  }
  partion *assigned = createPartion(ptr->id, ptr->addr_front, need, 1);
  assigned->next = ptr;
  assigned->front = ptr->front;
  changeIdValue(ptr, 1);
  ptr->addr_front += need;
  ptr->size -= need;
  if (ptr->front != NULL)
  {
    ptr->front->next = assigned;
  }
  else
  {
    head = assigned;
  }

  ptr->front = assigned;
}

void recovery()
{
  printf("please input the id to recovery:");
  int id, flag = 0;
  scanf("%d", &id);
  partion *ptr = head;
  while (ptr != NULL)
  {
    if (id == ptr->id)
    {
      flag = 1;
      break;
    }
    ptr = ptr->next;
  }
  if (flag == 0)
  {
    puts("No such partion!");
    return;
  }
  if (ptr->flag == 0)
  {
    puts("This partion is not busy!");
    return;
  }
  if (ptr->front == NULL)
  {
    //第一个分区

    if (ptr->next == NULL || ptr->next->flag == 1)
    {
      //后面不空或后面没有
      ptr->flag = 0;
      return;
    }
    if (ptr->next->flag == 0)
    {
      //后面空
      ptr->size += ptr->next->size;
      ptr->flag = 0;
      if (ptr->next->next != NULL)
      {
        ptr->next->next->front = ptr;
      }
      ptr->next = ptr->next->next;

      free(ptr->next);
      return;
    }
  }
  if (ptr->next == NULL)
  {
    //最后一个分区
    if (ptr->front == NULL || ptr->front->flag == 1)
    {
      //前面不空或者前没有
      ptr->flag = 0;
      return;
    }
    if (ptr->front->flag == 0)
    {
      //前面为空
      ptr->front->size += ptr->size;
      ptr->front->next = NULL;
      free(ptr);
      return;
    }
  }
  if (ptr->front->flag == 0 && ptr->next->flag == 0)
  {
    //上下都空
    ptr->front->size += ptr->size + ptr->next->size;
    ptr->front->next = ptr->next->next;
    if (ptr->next->next != NULL)
    {
      ptr->next->next->front = ptr->front;
    }
    changeIdValue(ptr->front->next, -2); //更改id
    free(ptr->next);
    free(ptr);
    return;
  }
  if (ptr->front->flag == 0 && ptr->next->flag == 1)
  {
    //上空下不空
    ptr->front->size += ptr->size;
    ptr->front->next = ptr->next;
    ptr->next->front = ptr->front;
    changeIdValue(ptr->front->next, -1);
    free(ptr);
    return;
  }
  if (ptr->front->flag == 1 && ptr->next->flag == 0)
  {
    //上不空下空
    ptr->size += ptr->next->size;
    if (ptr->next->next != NULL)
    {
      ptr->next->next->front = ptr;
    }
    partion *p_next = ptr->next;  //保存一下下方为空的那个分区,以便一会释放 
    ptr->next = ptr->next->next;
    ptr->flag = 0;
    changeIdValue(ptr->next, -1);
    free(p_next);
    return;
  }
  if (ptr->front->flag == 1 && ptr->next->flag == 1)
  {
    //上下都不空
    ptr->flag = 0;
    return;
  }
}

void changeIdValue(partion *ptr, int delta)
{
  while (ptr != NULL)
  {
    ptr->id += delta;
    ptr = ptr->next;
  }
}

运行截图

  • 首次适应

    在这里插入图片描述
    在这里插入图片描述
  • 最佳适应

    在这里插入图片描述
    在这里插入图片描述
  • 内存回收

    在这里插入图片描述
    在这里插入图片描述

如有错误欢迎指正

posted @ 2020-12-05 15:03  闻风听雨  阅读(2542)  评论(0编辑  收藏  举报