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

  • 姓名:倪晓东
  • 学号:201821121020
  • 班级: 计算1811

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

解释你是如何记录内存空间使用情况,给出关键代码。

/*记录内存空间使用情况,每个进程分配到的内存块描述*/
struct allocated_block
{
    int pid;
    int size;                //进程大小
    int start_addr;          //进程分配到的内存块的起始地址
    char process_name[PROCESS_NAME_LEN];  //进程名
    struct allocated_block *next;   //指向下一个进程控制块
};

2. 记录空闲分区

用什么样的方法记录内存空闲区,给出关键代码。

//空闲分区,描述每一个空闲块的数据结构
struct free_block_type
{
    int size;        //空闲块大小
    int start_addr;  //空闲块起始位置
    struct free_block_type *next;  //指向下一个空闲块
};
//指向内存中空闲块链表的首地址
struct free_block_type *free_block= NULL;

  空闲分区链表:

//按首次适配算法重新整理内存空闲块链表,按空闲块首地址排序
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;
}

  

3. 内存分配算法

使用首次适配算法内存分配:

//按照首次适应算法给新进程分配内存空间
int allocate_FF(struct allocated_block *ab)
{
    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;
}

4. 内存释放算法

int exit()
{
    struct allocated_block *allocated_ab,*allocated_pre;
    struct free_block_type *free_ab,*free_pre;
    free_pre= free_block;
    allocated_pre= allocated_block_head;
    if(free_pre!= NULL)   //链表不为空 
    {
        free_ab= free_pre->next;
        while(free_ab!= NULL)
        {
            free(free_pre);   //释放当前节点 
            free_pre= free_ab; 
            free_ab= free_ab->next; //节点后移 
        }
    }
    if(allocated_pre!= NULL)
    {
        allocated_ab= allocated_pre->next;
        while(allocated_ab!= NULL)
        {
            free(allocated_pre);  //释放节点 
            allocated_pre= allocated_ab;
            allocated_ab= allocated_ab->next;  //节点后移 
        }
    }
    allocated_ab= allocated_ab->next;
    return 0;
}

删除进程,归还分配的存储空间,并删除描述该进程内存分配的结点

void kill_process()
{
    struct allocated_block *ab;
    int pid;
    printf("Kill Process,pid=");//删除进程号为
    scanf("%d",&pid);
    getchar();
    ab= find_process(pid);  //找到pid对应的链表节点
    if(ab!= NULL)
    {
        free_mem(ab);  //释放ab所表示的分配区
        dispose(ab);   //释放ab数据结构结点
    }
}

在进程分配链表中寻找指定进程

struct allocated_block* find_process(int pid)
{
    struct allocated_block *ab= allocated_block_head;
    if(ab== NULL)
    {
        printf("不存在!\n");
        return NULL;
    }
    while(ab->pid!= pid&&ab->next!= NULL)//查找整个链表 
        ab= ab->next;
    if(ab->next== NULL&&ab->pid!= pid)//找不到 
    {
        printf("error!\n");
        return NULL;
    }
    return ab;
}

  

5. 运行结果

(1)产生测试数据

设置内存大小为1000,每次为进程分配1-100内存大小:

 设置内存大小为200,每次为进程分配1-20内存大小:

(2)解释结果

内存总大小为200,每次为进程分配1-20内存

 如图所示,创建的第一个进程号PID=1,进程名称为PEOCESSNAME-01,内存起始地址为0,内存大小为2,空闲区首地址为2,剩余内存198。

 如图所示,创建的第二个进程号PID=2,进程名称为PEOCESS-02,内存起始地址为2,分配到的内存大小为8,空闲区首地址为10,剩余内存190。

  如图所示,创建的第二个进程号PID=3,进程名称为PEOCESS-03,内存起始地址为10,分配到的内存大小为15,空闲区首地址为25,剩余内存175。

  如图所示,创建的第二个进程号PID=4,进程名称为PEOCESS-04,内存起始地址为25,分配到的内存大小为1,空闲区首地址为26,剩余内存174。

 小结:

       首次适配算法从空闲区的第一个表目起查找该表,把最先能够满足要求的空闲区分配给进程,这种方法目的在于减少查找时间。为适应这种算法,空闲区链中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。但是在实际使用过程中,由于优先使用低址的可用空闲区,低址部分被不断进行分配,但又不能保证刚好完全利用,所以会留下很多不能被使用小空闲区,而且每次为进程分配内存从低址开始寻找,就要和这些小空闲区适配,会影响速率。

  • 姓名:倪晓东
  • 学号:201821121020
  • 班级: 计算1811

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

解释你是如何记录内存空间使用情况,给出关键代码。

/*记录内存空间使用情况,每个进程分配到的内存块描述*/
struct allocated_block
{
    int pid;
    int size;                //进程大小
    int start_addr;          //进程分配到的内存块的起始地址
    char process_name[PROCESS_NAME_LEN];  //进程名
    struct allocated_block *next;   //指向下一个进程控制块
};

2. 记录空闲分区

用什么样的方法记录内存空闲区,给出关键代码。

//空闲分区,描述每一个空闲块的数据结构
struct free_block_type
{
    int size;        //空闲块大小
    int start_addr;  //空闲块起始位置
    struct free_block_type *next;  //指向下一个空闲块
};
//指向内存中空闲块链表的首地址
struct free_block_type *free_block= NULL;

  空闲分区链表:

//按首次适配算法重新整理内存空闲块链表,按空闲块首地址排序
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;
}

  

3. 内存分配算法

使用首次适配算法内存分配:

//按照首次适应算法给新进程分配内存空间
int allocate_FF(struct allocated_block *ab)
{
    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;
}

4. 内存释放算法

int exit()
{
    struct allocated_block *allocated_ab,*allocated_pre;
    struct free_block_type *free_ab,*free_pre;
    free_pre= free_block;
    allocated_pre= allocated_block_head;
    if(free_pre!= NULL)   //链表不为空 
    {
        free_ab= free_pre->next;
        while(free_ab!= NULL)
        {
            free(free_pre);   //释放当前节点 
            free_pre= free_ab; 
            free_ab= free_ab->next; //节点后移 
        }
    }
    if(allocated_pre!= NULL)
    {
        allocated_ab= allocated_pre->next;
        while(allocated_ab!= NULL)
        {
            free(allocated_pre);  //释放节点 
            allocated_pre= allocated_ab;
            allocated_ab= allocated_ab->next;  //节点后移 
        }
    }
    allocated_ab= allocated_ab->next;
    return 0;
}

删除进程,归还分配的存储空间,并删除描述该进程内存分配的结点

void kill_process()
{
    struct allocated_block *ab;
    int pid;
    printf("Kill Process,pid=");//删除进程号为
    scanf("%d",&pid);
    getchar();
    ab= find_process(pid);  //找到pid对应的链表节点
    if(ab!= NULL)
    {
        free_mem(ab);  //释放ab所表示的分配区
        dispose(ab);   //释放ab数据结构结点
    }
}

在进程分配链表中寻找指定进程

struct allocated_block* find_process(int pid)
{
    struct allocated_block *ab= allocated_block_head;
    if(ab== NULL)
    {
        printf("不存在!\n");
        return NULL;
    }
    while(ab->pid!= pid&&ab->next!= NULL)//查找整个链表 
        ab= ab->next;
    if(ab->next== NULL&&ab->pid!= pid)//找不到 
    {
        printf("error!\n");
        return NULL;
    }
    return ab;
}

  

5. 运行结果

(1)产生测试数据

设置内存大小为1000,每次为进程分配1-100内存大小:

 设置内存大小为200,每次为进程分配1-20内存大小:

(2)解释结果

内存总大小为200,每次为进程分配1-20内存

 如图所示,创建的第一个进程号PID=1,进程名称为PEOCESSNAME-01,内存起始地址为0,内存大小为2,空闲区首地址为2,剩余内存198。

 如图所示,创建的第二个进程号PID=2,进程名称为PEOCESS-02,内存起始地址为2,分配到的内存大小为8,空闲区首地址为10,剩余内存190。

  如图所示,创建的第二个进程号PID=3,进程名称为PEOCESS-03,内存起始地址为10,分配到的内存大小为15,空闲区首地址为25,剩余内存175。

  如图所示,创建的第二个进程号PID=4,进程名称为PEOCESS-04,内存起始地址为25,分配到的内存大小为1,空闲区首地址为26,剩余内存174。

 小结:

       首次适配算法从空闲区的第一个表目起查找该表,把最先能够满足要求的空闲区分配给进程,这种方法目的在于减少查找时间。为适应这种算法,空闲区链中的空闲分区要按地址由低到高进行排序。该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。但是在实际使用过程中,由于优先使用低址的可用空闲区,低址部分被不断进行分配,但又不能保证刚好完全利用,所以会留下很多不能被使用小空闲区,而且每次为进程分配内存从低址开始寻找,就要和这些小空闲区适配,会影响速率。

猜你喜欢

转载自www.cnblogs.com/qq1803085022/p/12905642.html