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

  • 姓名:祁翌炀
  • 学号:201821121019
  • 班级:计算1811

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

首先建立一个进程链表,对每个进程进行空间的分配,创建新进程,在创建进程的时候进行分配空间和pid

int create_process()
{
    struct allocated_block *ab;
    int size;//大小
    int ret;
    ab= (struct allocated_block*)malloc(sizeof(struct allocated_block));
    if(!ab)
        exit(-5);
    ab->next= NULL;
    pid++;
    sprintf(ab->process_name,"进程-%02d",pid);//此处为进程的pid号,pid号为从0开始
    ab->pid= pid;
    
    for(;;)
    {
        size=rand()%51+50;//此处为随机分配内存,50-100
        printf("Memory for %s is %d\n",ab->process_name,size);
        if(size> 0)
        {
            ab->size= size;
            break;
        }
        else
            printf("The size have to greater than zero!Please input again!");
    }
    ret= allocate_mem(ab);
    if((ret== 1)&&(allocated_block_head== NULL))  //如果此时未赋值,则赋值
    {
        allocated_block_head= ab;
        return 1;
    }
    else if(ret== 1)  //分配成功,将该已分配块的描述插入已分配链表
    {
        ab->next= allocated_block_head;
        allocated_block_head= ab;
        return 2;
    }
    else if(ret== -1)  //分配不成功
    {
        printf("Allocation fail.\n");
        free(ab);
        return -1;
    }
    return 3;
}

 此处为展示函数,展示内存空间使用情况

int showmemuse()
{
    struct free_block_type *fbt= free_block;
    struct allocated_block *ab= allocated_block_head;
    printf("-------------------------------------------------------------\n");
    printf("Use Memory:\n");
    printf("%10s %20s %10s %10s\n","PID","ProcessName","start_addr","size");
    while(ab!= NULL)
    {
        printf("%10d %20s %10d %10d\n",ab->pid,ab->process_name,ab->start_addr,ab->size);
        ab= ab->next;
    }
    printf("-------------------------------------------------------------\n"); 
    printf("Free Memory:\n");
    printf("%20s %20s\n","     start_addr","     size");
    while(fbt!= NULL)
    {
        printf("%20d %20d\n",fbt->start_addr,fbt->size);
        fbt= fbt->next;
    }
    printf("\n");
    return 1;
}

 

2. 记录空闲分区

首先定义空闲区块的结构体,大小,位置,next指针

struct free_block_type
{
    int size;        //空闲块大小
    int start_addr;  //空闲块起始位置
    struct free_block_type *next;  //指向下一个空闲块
};
//指向内存中空闲块链表的首地址
struct free_block_type *free_block= NULL;
//按FF算法重新整理内存空闲块链表,按空闲块首地址排序
int rearrange_FF()
{
    struct free_block_type *head= free_block;
    struct free_block_type *forehand,*pre,*rear;
    int i;
    if(head== NULL)
        return -1;
    for(i= 0;i< free_block_count-1;i++)
    {
        forehand= head;
        pre= forehand->next;
        rear= pre->next;
        while(pre->next!= NULL)
        {
            if(forehand== head&&forehand->start_addr>= pre->start_addr)
            {
                //比较空闲链表中第一个空闲块与第二个空闲块的开始地址的大小
                head->next= pre->next;
                pre->next= head;
                head= pre;
                forehand= head->next;
                pre= forehand->next;
                rear= pre->next;
            }
            else if(pre->start_addr>= rear->start_addr)
            {
                //比较链表中其它相邻两个结点的开始地址的大小
                pre->next= rear->next;
                forehand->next= rear;
                rear->next= pre;
                forehand= rear;
                rear= pre->next;
            }
            else
            {
                forehand= pre;
                pre= rear;
                rear= rear->next;
            }
        }
    }
    return 0;
}

 同理可得BF与WF的算法与FF不同,但是结构相似,不同处在于比较的地方不同

//按BF算法重新整理内存空闲块链表,按空闲块大小从小到大排序
int rearrange_BF()
{
    struct free_block_type *head= free_block;
    struct free_block_type *forehand,*pre,*rear;
    int i;
    if(head== NULL)
        return -1;
    for(i= 0;i< free_block_count-1;i++)
    {
        forehand= head;
        pre= forehand->next;
        rear= pre->next;
        while(pre->next!= NULL)
        {
            if(forehand== head&&forehand->size<= pre->size)
            {
                //比较空闲链表中第一个空闲块与第二个空闲块的空间的大小
                head->next= pre->next;
                pre->next= head;
                head= pre;
                forehand= head->next;
                pre= forehand->next;
                rear= pre->next;
            }
            else if(pre->size<= rear->size)
            {
                //比较链表中其它相邻两个结点的空间的大小
                pre->next= rear->next;
                forehand->next= rear;
                rear->next= pre;
                forehand= rear;
                rear= pre->next;
            }
            else
            {
                forehand= pre;
                pre= rear;
                rear= rear->next;
            }
        }
    }
    return 0;
}

//按WF算法重新整理内存空闲块链表,按空闲块大小从大到小排序
int rearrange_WF()
{
    struct free_block_type *head= free_block;
    struct free_block_type *forehand,*pre,*rear;
    int i;
    if(head== NULL)
        return -1;
    for(i= 0;i< free_block_count-1;i++)
    {
        forehand= head;
        pre= forehand->next;
        rear= pre->next;
        while(pre->next!= NULL)
        {
            if(forehand== head&&forehand->size>= pre->size)
            {
                //比较空闲链表中第一个空闲块与第二个空闲块空间的大小
                head->next= pre->next;
                pre->next= head;
                head= pre;
                forehand= head->next;
                pre= forehand->next;
                rear= pre->next;
            }
            else if(pre->size>= rear->size)
            {
                //比较链表中其它相邻两个结点的空间的大小
                pre->next= rear->next;
                forehand->next= rear;
                rear->next= pre;
                forehand= rear;
                rear= pre->next;
            }
            else
            {
                forehand= pre;
                pre= rear;
                rear= rear->next;
            }
        }
    }
    return 0;
}

 

3. 内存分配算法

First Fit:从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法的目的在于减少查找时间。

为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,

在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。

int allocate_FF(struct allocated_block *ab)//first fit
{
    int ret;
    struct free_block_type *pre= NULL,*ff= free_block;
    if(ff== NULL)
        return -1;
    while(ff!= NULL)
    {
        if(ff->size>= ab->size)
        {
            ret= allocate(pre,ff,ab);
            break;
        }
        pre= ff;
        pre= pre->next;
    }
    if(ff== NULL&&current_free_mem_size> ab->size)
        ret= mem_retrench(ab);
    else
        ret= -2;
    rearrange_FF();
    return ret;
}

 

Best Fit:从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使

碎片尽量小。为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一

个满足要求的自由分区分配。该算法保留大的空闲区,但造成许多小的空闲区。

int allocate_BF(struct allocated_block *a)//best fit
{
    int ret;
    struct free_block_type *pre= NULL,*bf= free_block;
    if(bf== NULL)
        return -1;
    while(bf!= NULL)
    {
        if(bf->size>= ab->size)
        {
            ret= allocate(pre,bf,ab);
            break;
        }
        pre= bf;
        pre= pre->next;
    }
    if(bf== NULL&&current_free_mem_size> ab->size)
        ret= mem_retrench(ab);
    else
        ret= -2;
    rearrange_BF();
    return ret;
}

 

Worst Fit:从全部空闲区中找出能满足作业要求的、且大小最大的空闲分区,从而使链表中

的结点大小趋于均匀,适用于请求分配的内存大小范围较窄的系统。为适应此算法,空闲分区表(空闲区链)中的空

闲分区按大小从大到小进行排序,自表头开始查找到第一个满足要求的自由分区分配。该算法保留小的空闲区,尽量

减少小的碎片产生。

int allocate_WF(struct allocated_block *ab)//worst fit
{
    int ret;
    struct free_block_type *wf= free_block;
    if(wf== NULL)
        return -1;
    if(wf->size>= ab->size)
        allocate(NULL,wf,ab);
    else if(current_free_mem_size>= ab->size)
        ret= mem_retrench(ab);
    else
        ret= -2;
    rearrange_WF();
    return ret;
}

 

4. 内存释1放算法

 清除输入pid的进程,首先定义后声明pid,根据链表查找pid,随后进行free释放内存和数据,并且返还给未使用的内存大小中

void kill_process() //清楚当前pid的进程
{
    struct allocated_block *ab;
    int pid;
    printf("Kill Process,pid=");
    scanf("%d",&pid);
    getchar();
    ab= find_process(pid);
    if(ab!= NULL)
    {
        free_mem(ab);  //释放ab所表示的分配区
        dispose(ab);   //释放ab数据结构结点
    }
}
//将ab所表示的已分配区归还,并进行可能的合并
int free_mem(struct allocated_block *ab)
{
    int algorithm= ma_algorithm;
    struct free_block_type *fbt,*pre,*work;
    fbt= (struct free_block_type*)malloc(sizeof(struct free_block_type));
    if(!fbt)
        return -1;
    pre= free_block;
    fbt->start_addr= ab->start_addr;
    fbt->size= ab->size;
    fbt->next= NULL;
    if(pre!= NULL)
    {
        while(pre->next!= NULL)
            pre= pre->next;
        pre->next= fbt;
    }
    else
    {
        free_block= fbt;
    }
    rearrange_FF();
    pre= free_block;
    work= pre->next;
    while(work!= NULL)
    {
        if(pre->start_addr+ pre->size== work->start_addr)
        {
            pre->size+= work->size;
            free(work);
            work= pre->next;
        }
        else
        {
            pre= work;
            work= work->next;
        }
    }
    current_free_mem_size+= ab->size;
    return 1;
}

 

5. 运行结果

(1)产生测试数据

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

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

此处为实验测试的main函数

int main()
{ 
    free_block= init_free_block(mem_size);   
    printf("请选择内存分配算法\n");
    printf("1:首次适应算法\n");
    printf("2:最佳适应算法\n");
    printf("3:最差适应算法\n");
    char choose;
    fflush(stdin);
    choose= getchar();
    getchar();
    switch (choose)
    {
        case '1':
             rearrange(1);
            break;
        case '2':
             rearrange(2);
            break;
        case '3':
             rearrange(3);
            break;
    }
    int count;
    printf("ps:内存大小自动定为50-100,所以输入的进程次数尽量少于10!\n"); 
    printf("算法已经分配完成,请输入要创建的进程次数:");    
    scanf("%d",&count);
    int pid= 0;
    int i;
        for(i=0;i<count;i++){
            create_process();//添加新进程 
            showmemuse();//显示内存使用情况 
        } 
    while(1)
    {
    printf("是否要删除进程?(输入no退出本程序)y/n:");
    fflush(stdin);
    choose= getchar();
    if(choose=='y')
    {
            kill_process();
            count--;    
            showmemuse();
    }
    else
    break;
    }
    
}

 

(2)解释结果

 

 

中间不截了

 

 

删除进程 5

可以看到进程5没了,

然后退出程序。

 

posted @ 2020-05-17 16:05  QBB  阅读(217)  评论(0编辑  收藏  举报