操作系统第5次实验报告:内存管理

 


  • 姓名 邹文兵
  • 学号 201821121028
  • 班级 计算1811

1. 记录内存空间使用情况

记录内存空间使用情况:首先程序采用链式存储结构存储空闲分区链。定义一个空闲分区表的结构体,包括空闲分区表的id号,首地址、分区大小、分配标志。然后用结构体表示链表的每一个节点,包括分区表结构体、front和next指针。在进行内存分配时对不同进程进行适当地址分配,并记录分配信息在结构体中,最后定义一个p指针,让p指针遍历空闲分区链表将内存空间打印出来。

 

实现代码:

void show()
{
    printf("------------------------------------------------------------------\n");
    printf("内存分配情况:\n");
    Free_Node *p=block_first->next;
    while(p)
    {
        cout<<"分区号:";
        if (p->date.ID==FREE) printf("FREE\t");
        else printf("%d\t",p->date.ID);
        printf("起始地址:%d\t",p->date.address);
        printf("内存大小:%d\t",p->date.size);
        printf("分区状态:");
        if (p->date.flag==FREE)
            printf("空闲\n");
        else
             printf("已分配\n");
        p=p->next;
    }
}

2. 记录空闲分区

空闲分区表的结构体:

typedef struct freeArea//首先定义空闲区分表结构
 {
int flag;
int size;
int ID;
int address;
 }Elemtype;
 
typedef struct Free_Node
{
    Elemtype date;
    struct Free_Node *front;
    struct Free_Node *next;
}Free_Node,*FNodeList;

 

3. 内存分配算法

1、首次适应算法:

首次适应算法比较简单,只要找到满足条件的空闲区,就将此区的空间分配给进程。首先,用P指针遍历链表,找到第一个空间大于或者等于请求大小的位置,将此空间分配给进程,当此空闲区大小大于请求空间大小时,将空闲区分为两部分,一部分分配给进程,另一部分为空闲区,它的大小为之前空闲区大小减去分配给进程的空间大小。

int first_fit(int ID,int size)//首次适应算法
{
     FNodeList temp=(FNodeList)malloc(sizeof(Free_Node));
     Free_Node *p=block_first->next;
     temp->date.ID=ID;
     temp->date.size=size;
     temp->date.flag=BUSY;
    while(p)
    {
        if (p->date.flag==FREE && p->date.size==size)//请求大小刚好满足
        {
            p->date.flag=BUSY;
            p->date.ID=ID;
            return 1;
            break;
        }
        if (p->date.flag==FREE && p->date.size>size)//说明还有其他的空闲区间
        {
            temp->next=p;
            temp->front=p->front;
            temp->date.address=p->date.address;
          p->front->next=temp;
          p->front=temp;
          p->date.address=temp->date.address+temp->date.size;
          p->date.size-=size;
          return 1;
          break;
        }
        p=p->next;
    }
    return 0;
}
 

2、最佳适应算法:

首先,定义一个p指针,让p指针遍历空闲分区链表,当找到第一个满足进程请求空间大小的空闲区时,记录此位置,并且保存请求大小与空闲分区实际大小的差值记为a,然后让p指针继续遍历空闲分区链表,每当满足请求内存大小小于空闲区大小时,就记录两者的差值并且记录为b,比较a与b的大小关系,当a>b时,将b的值赋予a,并且修改记录位置为此空闲区的位置。若,a<=b,不做操作。继续遍历链表,重复上面的操作,直到p->next指向null为止。

int best_fit(int ID,int size)//最佳适应算法
{
    int surplus;//记录可用内存与需求内存的差值
    FNodeList temp=(FNodeList)malloc(sizeof(Free_Node));
    Free_Node *p=block_first->next;
    temp->date.ID=ID;
    temp->date.size=size;
    temp->date.flag=BUSY;
    Free_Node *q=NULL;//记录最佳位置
    while(p)//遍历链表,找到第一个可用的空闲区间将他给q
    {
        if (p->date.flag==FREE&&p->date.size>=size)
        {
            q=p;
            surplus=p->date.size-size;
            break;
        }
        p=p->next;
    }
    while(p)//继续遍历,找到更加合适的位置
    {
        if (p->date.flag==FREE&&p->date.size==size)
        {
            p->date.flag=BUSY;
            p->date.ID=ID;
            return 1;
            break;
        }
        if (p->date.flag==FREE&&p->date.size>size)
        {
            if (surplus>p->date.size-size)
            {
                surplus=p->date.size-size;
                q=p;
            }
 
        }
        p=p->next;
    }
    if (q==NULL)//如果没有找到位置
    {
        return 0;
    }
    else//找到了最佳位置
    {
        temp->next=q;
        temp->front=q->front;
        temp->date.address=q->date.address;
        q->front->next=temp;
        q->front=temp;
        q->date.size=surplus;
        q->date.address+=size;
        return 1;
    }
}

 

4. 内存释放算法

内存回收算法:

内存回收时,回收分区与空闲分区有四种关系。第一种情况为回收分区r上临一个空闲分区,此时应该合并为一个连续的空闲区,其始址为r上相邻的分区的首地址,而大小为两者大小之和。第二种情况为回收分区r与下相邻空闲分区,合并后仍然为空闲区,该空闲区的始址为回收分区r的地址。大小为两者之和,第三种情况为回收部分r与上下空闲区相邻,此时将这三个区域合并,始址为r上相邻区域的地址,大小为三个分区大小之和。当回收部分r上下区域都为非空闲区域,此时建立一个新的空闲分区,并且加入到空闲区队列中去。

int free(int ID)//主存回收
{
    Free_Node *p=block_first->next;
    while(p)
    {
        if (p->date.ID==ID)//找到要回收的ID区域
        {
            p->date.flag=FREE;
            p->date.ID=FREE;
            //判断P与前后区域关系
            if (p->front->date.flag==FREE&&p->next->date.flag!=FREE)
            {
                p->front->date.size+=p->date.size;
                p->front->next=p->next;
                p->next->front=p->front;
            }
            if (p->front->date.flag!=FREE&&p->next->date.flag==FREE)
            {
                p->date.size+=p->next->date.size;
                if(p->next->next)
                {
                    p->next->next->front=p;
                p->next = p->next->next;
                }
                else p->next=p->next->next;
            }
            if(p->front->date.flag==FREE&&p->next->date.flag==FREE)
            {
                p->front->date.size+=p->date.size+p->next->date.size;
                if(p->next->next)
                {
                p->next->next->front=p->front;
                p->front->next=p->next->next;
                }
                else p->front->next=p->next->next;
            }break;
        }
        p=p->next;
    }
    cout<<"回收成功!"<<endl;
    return 1;
}

5. 运行结果

(1)产生测试数据

写程序,产生测试数据(随机)。给出你的源码,以及你生成的测试数据是什么。

随机为3个进程分配、释放内存10次以上,即随机产生10组以上数据:(进程Pi 分配内存大小) 或者 (进程Pi结束)

int alloc(int tag)
{
    int ID1,ID2,ID3;
    int size1,size2,size3;
    int i=0;
    srand((unsigned)time(NULL));
    for(i;i<10;i++)   //随机生成十组数据 
    {    
        tag++;
        ID1=rand()%100;    //进程1 
        size1=rand()%100;
        if (tag==1) first_fit(ID1,size1);//采用首次适应算法            
        else  best_fit(ID1,size1);//采用最佳适应算法 
        ID2=rand()%100;   //进程2 
        size2=rand()%100;
        if (tag==1) first_fit(ID2,size2);//采用首次适应算法            
        else  best_fit(ID2,size2);//采用最佳适应算法 
        ID3=rand()%100;    //进程3 
        size3=rand()%100;
        if (tag==1) first_fit(ID3,size3);//采用首次适应算法            
        else  best_fit(ID3,size3);//采用最佳适应算法 
        show();
        free(ID1); //进程1主存回收
        show();
        free(ID2); //进程2主存回收
        show();
        free(ID3); //进程3主存回收
        show();
    }         
}

运行结果截图:

(2)解释结果

第一次内存分配:进程1的进程号为44,申请内存大小为24,起始地址从空闲的0开始,即0到23处的内存分配给进程1;

第二次内存分配:进程2的进程号为70,申请内存大小为89,起始地址从空闲的24开始,即24到112处内存分配给进程2;

第三次内存分配:进程3的进程号为9,申请内存大小为21,起始地址从空闲的113开始,即113到133处内存分配给进程3;

由于初始化空闲内存大小为640,所以除去已分配的内存外其余还剩506的空闲内存,从134到640都为空闲内存。

第一次回收主存:回收进程1的内存,使地址0到23处地址状态改为空闲,即0到23和134到640都为空闲内存;

第二次回收主存:回收进程2的内存,使地址24到112处地址状态改为空闲,即0到112和134到640都为空闲内存;

第三次回收主存:回收进程3的内存,使地址113到133处地址状态改为空闲,即0到640都为空闲内存;

posted @ 2020-05-17 01:01  zouwenbin  阅读(376)  评论(0编辑  收藏  举报