西北农林科技大学操作系统实验三(3)——Linux系统设计

编写伙伴算法

本程序实现了基本的伙伴算法。设计步骤:
(1)、初始化:把4096个页全部分配到最高等级的空闲区上。
(2)、分配算法:用户输入作业名和作业所需要的页数,该算法会根据伙伴算法的思想一级一级的找到合适的页框块。然后把该块的相关信息填写在已分配分区中。
(3)、回收算法:未分配算法的逆算法:用户输入作业名后,先根据作业名在分配区找到页框块,然后根据伙伴算法的思想一级一级的进行合并。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
//页框块
struct PageBlock
{
    char Job[20];//作业的名字
    int begin_page;//开始页的编号
    int end_page;//结束页的编号
    int block_num;//页框块编号=(end_page+1)/2^k);
    struct PageBlock* link;//下节点
};
typedef struct PageBlock page_block;
//空闲分区
struct FreeArea
{
    page_block* free_list;//空闲分区块头
    int nr_free;//该空闲分区有几个页框块
} free_area[11];

page_block* used;//已分配的区块的块头
page_block* fp;//回收时用
page_block* per;//fp的前指针
/*********************************************************/
//把b尾插入到以head为首的队列中
void Insert(page_block* head, page_block* b, int k)
{
    if(head->link == NULL)
    {
        head->link = b;
        b->link=NULL;
    }
    else
    {
        page_block *ptr1 = head;
        while(ptr1->link != NULL)
        {
            ptr1=ptr1->link;
        }
        ptr1->link = b;
        b->link = NULL;
    }
    b->block_num=(b->end_page+1)/pow(2,k);
}
//判断伙伴是不是空闲
int IsPaFree(int block_num, int k)
{
    int pa;
    //寻找他的伙伴
    if(block_num%2 == 0)
        pa = block_num-1;//偶数他的伙伴为他-1
    else
         pa = block_num+1;//奇数他的伙伴为他+1
    page_block* pt=free_area[k].free_list;
    page_block* pt1=pt->link;
    while(pt1 != NULL)
    {
        if(pt1->block_num == pa)
          break;
          pt=pt->link;
          pt1=pt->link;
    }
    if(pt1 == NULL)
        return 0;
    else
    {
      //把伙伴从现在等级的空闲区中取下
      pt->link = pt1->link;
      fp=pt1;
      return 1;
    }
}
/*********************************************************/
//初始化
void Init()
{
    used=(page_block*)malloc(sizeof(page_block));
    int i = 0;
    for(i = 0; i < 11; i++)
    {
        //初始所有空闲域都为空
        free_area[i].free_list = (page_block*)malloc(sizeof(page_block));
        free_area[i].free_list->link=NULL;
        free_area[i].nr_free=0;
    }
    //将4096个页分配到10的空闲域中
    for(i = 0; i < 4; i++)
    {
        //printf("bbb\n");
        page_block* b1 = (page_block*)malloc(sizeof(page_block));
        b1->begin_page=i*1024;
        b1->end_page=(i+1)*1024-1;
        Insert(free_area[10].free_list, b1,10);
        free_area[10].nr_free++;
    }
}
//分配函数
void alloct(char Job[], int pages)
{

    int order ;
    if(pages != 1)
      order = log2(pages-1)+1;
     else
        order = 1;
    int i = order;
    //寻找空闲块
    for(i=order; i < 11; i++)
    {
       if(free_area[i].nr_free != 0)
                break;
    }
        //从高阶的空闲区中摘下一个页框块,ptr为要摘下的
        page_block* ptr = free_area[i].free_list->link;
        free_area[i].free_list->link=ptr->link;
        free_area[i].nr_free--;
        i--;
      while(i != order-1)//一定是order-1
      {
          page_block* ptr1 =(page_block*)malloc(sizeof(page_block));
          ptr1->begin_page=ptr->begin_page;
          ptr1->end_page=ptr1->begin_page+pow(2,i)-1;
          ptr1->link=NULL;
          Insert(free_area[i].free_list,ptr1,i);//把分割的一块插入到现在的空闲区中
          free_area[i].nr_free++;
          //另一块面临继续分割的可能或者会被利用
          ptr->begin_page=ptr1->end_page+1;
          ptr->block_num=(ptr->end_page+1)/pow(2,i);//另一块的伙伴号
          i--;
      }
      strcpy(ptr->Job,Job);
      //把该分区插入到已分配分区
      Insert(used, ptr,order);
}
//回收函数
void reclaim(char Job[])
{
    page_block* ptr=used;
    page_block* ptr1=ptr->link;
    while(ptr1 != NULL)
    {
        //找到该作业所在的位置
        if(strcmp(ptr1->Job,Job) == 0)
           break;
        ptr=ptr->link;
        ptr1=ptr->link;
    }
    if(ptr1 == NULL)
    {
        printf("没有改作业\n");
        return;
    }
    ptr->link=ptr1->link;//把作业从已分配分区中摘出来。
    int o=ptr1->end_page-ptr1->begin_page+1;
    int order = log2(o-1)+1;//找到该块的等级
    //printf("bl %d\n",ptr1->block_num);
    if(IsPaFree(ptr1->block_num, order)==0)//伙伴不空闲
    {
        Insert(free_area[order].free_list,ptr1,order);

    }
    else //伙伴空闲
    {
        int i = order;
        while(i<10)
        {
            page_block* newblock=ptr1;
          if(ptr1->block_num < fp->block_num)//奇数,ptr1在前
          {
              newblock->end_page=fp->end_page;
              free(fp);
          }
          else                            //偶数,fp在前
          {
              newblock->begin_page=fp->begin_page;
              free(fp);
          }
          free_area[i].nr_free--;
          i++;
          int block_num=(newblock->end_page+1)/pow(2,i);
          if( i==10 || IsPaFree(block_num, i)==0)//如果在上一等级伙伴不空闲,最高级直接插入即可
          {
              Insert(free_area[i].free_list,newblock,i);//插入到上一级队列
              free_area[i].nr_free++;
              break;
          }
           else
            ptr1 = newblock;//下一级的伙伴空闲,继续合并
        }
    }
}
//显示函数
void show()
{
  printf("已分配分区:\n");
  printf("作业名\t分区的起始页\t分区的终止页\t伙伴号\n");
  page_block* ptr=used;
  page_block* ptr1=ptr->link;
  while(ptr1!=NULL)
  {
      printf("%s\t%d\t\t%d\t\t%d\n",ptr1->Job,ptr1->begin_page,ptr1->end_page,ptr1->block_num);
      ptr=ptr->link;
      ptr1=ptr->link;
  }
  printf("空闲分区\n");
  printf("分区等级\t分区的起始页\t分区的终止页\t伙伴号\n");
  int i = 0;
  for(i = 10; i>=0; i--)
  {
      if(free_area[i].nr_free != 0)
      {
          page_block* ptr2=free_area[i].free_list;
          page_block* ptr3=ptr2->link;
          while(ptr3 != NULL)
          {
              printf("%d\t\t%d\t\t%d\t\t%d\n",i,ptr3->begin_page,ptr3->end_page,ptr3->block_num);
              ptr2=ptr2->link;
              ptr3=ptr2->link;
          }
      }
      printf("\n");
  }
}
/*********************************************************/
int main()
{
    Init();//初始化,所有的页都在最大的空闲区,即k为10的
    int d = 0;
    while(1)
    {
        system("cls");
        printf("\n\n");
        printf("\t\t请输入选项:\n");
        printf("\t\t1.分配内存\n");
        printf("\t\t2.回收内存\n");
        printf("\t\t3.显示分配区\n");
        printf("\t\t0.退出系统\n");
        scanf("%d",&d);
        if(d == 1)
        {
            printf("请输入要分配的作业名及大小(单位:页):\n");
            char Job[10];
            int pages;
            scanf("%s%d",Job, &pages);
            alloct(Job, pages);
            getchar();
        }
        else if(d == 2)
        {
          printf("请输入要回收的作业名\n");
          char Job[10];
          scanf("%s",Job);
          reclaim(Job);
          getchar();
        }
        else if(d == 3)
        {
            show();
            getchar();
        }
        else if(d == 0)
        {
            exit(0);
        }
        getchar();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44029810/article/details/107787474